bool bson_find_create_table (bson_t *bson_schema, const char *table_name, bson_iter_t *iter_col) { bson_iter_t iter_json, iter_ary, iter_sql, iter_table_prop; bson_iter_init_find (&iter_json, bson_schema, "json") || DIE; BSON_ITER_HOLDS_ARRAY (&iter_json) || DIE; bson_iter_recurse (&iter_json, &iter_ary) || DIE; while (bson_iter_next (&iter_ary)) { (BSON_ITER_HOLDS_DOCUMENT (&iter_ary) || DIE); bson_iter_recurse (&iter_ary, &iter_sql) || DIE; if (bson_iter_find (&iter_sql, "create_table") && (BSON_ITER_HOLDS_DOCUMENT (&iter_sql) || DIE) && (bson_iter_recurse (&iter_sql, &iter_table_prop) || DIE) && (bson_iter_find (&iter_table_prop, "table_name") || DIE) && (BSON_ITER_HOLDS_UTF8 (&iter_table_prop) || DIE) && (strcmp (bson_iter_utf8 (&iter_table_prop, NULL), table_name) == 0) && (bson_iter_find (&iter_table_prop, "columns") || DIE) && (BSON_ITER_HOLDS_ARRAY (&iter_table_prop) || DIE)) { bson_iter_recurse (&iter_table_prop, iter_col) || DIE; return true; } } return (false); }
bool _mongoc_convert_document (mongoc_client_t *client, const bson_iter_t *iter, bson_t *doc, bson_error_t *error) { uint32_t len; const uint8_t *data; bson_t value; if (!BSON_ITER_HOLDS_DOCUMENT (iter)) { CONVERSION_ERR ("Invalid field \"%s\" in opts, should contain document," " not %s", bson_iter_key (iter), _mongoc_bson_type_to_str (bson_iter_type (iter))); } bson_iter_document (iter, &len, &data); if (!bson_init_static (&value, data, len)) { BSON_ERR ("Corrupt BSON in field \"%s\" in opts", bson_iter_key (iter)); } bson_destroy (doc); bson_copy_to (&value, doc); return true; }
/* * Start iterating the reply to an "aggregate", "find", "getMore" etc. command: * * {cursor: {id: 1234, ns: "db.collection", firstBatch: [...]}} */ bool _mongoc_cursor_cursorid_start_batch (mongoc_cursor_t *cursor) { mongoc_cursor_cursorid_t *cid; bson_iter_t iter; bson_iter_t child; const char *ns; uint32_t nslen; cid = (mongoc_cursor_cursorid_t *)cursor->iface_data; BSON_ASSERT (cid); if (bson_iter_init_find (&iter, &cid->array, "cursor") && BSON_ITER_HOLDS_DOCUMENT (&iter) && bson_iter_recurse (&iter, &child)) { while (bson_iter_next (&child)) { if (BSON_ITER_IS_KEY (&child, "id")) { cursor->rpc.reply.cursor_id = bson_iter_as_int64 (&child); } else if (BSON_ITER_IS_KEY (&child, "ns")) { ns = bson_iter_utf8 (&child, &nslen); _mongoc_set_cursor_ns (cursor, ns, nslen); } else if (BSON_ITER_IS_KEY (&child, "firstBatch") || BSON_ITER_IS_KEY (&child, "nextBatch")) { if (BSON_ITER_HOLDS_ARRAY (&child) && bson_iter_recurse (&child, &cid->batch_iter)) { cid->in_batch = true; } } } } return cid->in_batch; }
/* * If error is not set, set code from first document in array like * [{"code": 64, "errmsg": "duplicate"}, ...]. Format the error message * from all errors in array. */ static void _set_error_from_response (bson_t *bson_array, mongoc_error_domain_t domain, const char *error_type, bson_error_t *error /* OUT */) { bson_iter_t array_iter; bson_iter_t doc_iter; bson_string_t *compound_err; const char *errmsg = NULL; int32_t code = 0; uint32_t n_keys, i; compound_err = bson_string_new (NULL); n_keys = bson_count_keys (bson_array); if (n_keys > 1) { bson_string_append_printf ( compound_err, "Multiple %s errors: ", error_type); } if (!bson_empty0 (bson_array) && bson_iter_init (&array_iter, bson_array)) { /* get first code and all error messages */ i = 0; while (bson_iter_next (&array_iter)) { if (BSON_ITER_HOLDS_DOCUMENT (&array_iter) && bson_iter_recurse (&array_iter, &doc_iter)) { /* parse doc, which is like {"code": 64, "errmsg": "duplicate"} */ while (bson_iter_next (&doc_iter)) { /* use the first error code we find */ if (BSON_ITER_IS_KEY (&doc_iter, "code") && code == 0) { code = bson_iter_int32 (&doc_iter); } else if (BSON_ITER_IS_KEY (&doc_iter, "errmsg")) { errmsg = bson_iter_utf8 (&doc_iter, NULL); /* build message like 'Multiple write errors: "foo", "bar"' */ if (n_keys > 1) { bson_string_append_printf (compound_err, "\"%s\"", errmsg); if (i < n_keys - 1) { bson_string_append (compound_err, ", "); } } else { /* single error message */ bson_string_append (compound_err, errmsg); } } } i++; } } if (code && compound_err->len) { bson_set_error ( error, domain, (uint32_t) code, "%s", compound_err->str); } } bson_string_free (compound_err, true); }
/* {{{ proto WriteError[] WriteResult::getWriteErrors() Returns any write errors that occurred */ PHP_METHOD(WriteResult, getWriteErrors) { bson_iter_t iter, child; php_phongo_writeresult_t *intern; SUPPRESS_UNUSED_WARNING(return_value_ptr) SUPPRESS_UNUSED_WARNING(return_value_used) intern = Z_WRITERESULT_OBJ_P(getThis()); if (zend_parse_parameters_none() == FAILURE) { return; } array_init(return_value); if (bson_iter_init_find(&iter, intern->reply, "writeErrors") && BSON_ITER_HOLDS_ARRAY(&iter) && bson_iter_recurse(&iter, &child)) { while (bson_iter_next(&child)) { bson_t cbson; uint32_t len; const uint8_t *data; #if PHP_VERSION_ID >= 70000 zval writeerror; #else zval *writeerror = NULL; #endif if (!BSON_ITER_HOLDS_DOCUMENT(&child)) { continue; } bson_iter_document(&child, &len, &data); if (!bson_init_static(&cbson, data, len)) { continue; } #if PHP_VERSION_ID >= 70000 object_init_ex(&writeerror, php_phongo_writeerror_ce); if (!phongo_writeerror_init(&writeerror, &cbson TSRMLS_CC)) { zval_ptr_dtor(&writeerror); continue; } add_next_index_zval(return_value, &writeerror); #else MAKE_STD_ZVAL(writeerror); object_init_ex(writeerror, php_phongo_writeerror_ce); if (!phongo_writeerror_init(writeerror, &cbson TSRMLS_CC)) { zval_ptr_dtor(&writeerror); continue; } add_next_index_zval(return_value, writeerror); #endif } } }
static bool hippo_cursor_next(MongoDBDriverCursorData* data) { invalidate_current(data); data->next_after_rewind++; data->current++; if (data->is_command_cursor && bson_iter_next(&data->first_batch_iter)) { if (BSON_ITER_HOLDS_DOCUMENT(&data->first_batch_iter)) { const uint8_t *document = NULL; uint32_t document_len = 0; bson_iter_document(&data->first_batch_iter, &document_len, &document); data->zchild_active = true; return true; } } if (hippo_cursor_load_next(data)) { return true; } else { invalidate_current(data); } return false; }
void _aggregate_recurse_fill(bson_iter_t *iter, bson_t* new_doc, bson_t* existing_aggregate_doc, bson_t* merged_aggregate_doc, const char *key) { bson_iter_t child_iter; bson_t child_doc; while (bson_iter_next (iter)) { int new_key_length = strlen(bson_iter_key(iter)); if (strcmp("", key) != 0) { new_key_length += strlen(key) + 1; } char new_key[new_key_length]; if (strcmp("", key) == 0) { strcpy(new_key, bson_iter_key(iter)); } else { strcpy(new_key, key); strcat(new_key, "."); strcat(new_key, bson_iter_key(iter)); } if (strcmp("_id", new_key) == 0) { bson_value_t *existing_id = _aggregate_get_value_at_key(existing_aggregate_doc, "_id"); bson_append_value(merged_aggregate_doc, "_id", -1, existing_id); continue; } if (BSON_ITER_HOLDS_DOCUMENT (iter)) { const char *agg_key = NULL; const bson_value_t *agg_field = NULL; if (bson_iter_recurse (iter, &child_iter)) { if (bson_iter_next (&child_iter) && _aggregate_is_agg_operator(bson_iter_key(&child_iter))) { agg_key = bson_iter_key(&child_iter); agg_field = bson_iter_value(&child_iter); } if (agg_key && !bson_iter_next (&child_iter)) { bson_value_t *existing_value = _aggregate_get_value_at_key(existing_aggregate_doc, new_key); bson_value_t *new_doc_value = _aggregate_get_value_at_key(new_doc, (*agg_field).value.v_utf8.str + 1); bson_value_t * agg_result = _aggregate(existing_value, new_doc_value, agg_key); bson_append_value(merged_aggregate_doc, bson_iter_key(iter), -1, agg_result); continue; } } bson_append_document_begin (merged_aggregate_doc, bson_iter_key(iter), -1, &child_doc); if (bson_iter_recurse (iter, &child_iter)) { _aggregate_recurse_fill (&child_iter, new_doc, existing_aggregate_doc, &child_doc, new_key); } bson_append_document_end (merged_aggregate_doc, &child_doc); } else { bson_append_value(merged_aggregate_doc, bson_iter_key(iter), -1, bson_iter_value(iter)); } } }
/* {{{ proto array WriteResult::getUpsertedIds() Returns the identifiers generated by the server for upsert operations. */ PHP_METHOD(WriteResult, getUpsertedIds) { bson_iter_t iter, child; php_phongo_writeresult_t *intern; SUPPRESS_UNUSED_WARNING(return_value_ptr) SUPPRESS_UNUSED_WARNING(return_value_used) intern = Z_WRITERESULT_OBJ_P(getThis()); if (zend_parse_parameters_none() == FAILURE) { return; } array_init(return_value); if (bson_iter_init_find(&iter, intern->reply, "upserted") && BSON_ITER_HOLDS_ARRAY(&iter) && bson_iter_recurse(&iter, &child)) { while (bson_iter_next(&child)) { int32_t index; bson_iter_t outer; if (!BSON_ITER_HOLDS_DOCUMENT(&child) || !bson_iter_recurse(&child, &outer)) { continue; } if (!bson_iter_find(&outer, "index") || !BSON_ITER_HOLDS_INT32(&outer)) { continue; } index = bson_iter_int32(&outer); if (!bson_iter_find(&outer, "_id")) { continue; } if (BSON_ITER_HOLDS_OID(&outer)) { #if PHP_VERSION_ID >= 70000 zval zid; php_phongo_objectid_new_from_oid(&zid, bson_iter_oid(&outer) TSRMLS_CC); add_index_zval(return_value, index, &zid); #else zval *zid = NULL; MAKE_STD_ZVAL(zid); php_phongo_objectid_new_from_oid(zid, bson_iter_oid(&outer) TSRMLS_CC); add_index_zval(return_value, index, zid); #endif } else if (BSON_ITER_HOLDS_INT32(&outer)) { int32_t val = bson_iter_int32(&outer); add_index_long(return_value, index, val); } else if (BSON_ITER_HOLDS_INT64(&outer)) { int64_t val = bson_iter_int64(&outer); ADD_INDEX_INT64(return_value, index, val); } } } }
static int _score_tags (const bson_t *read_tags, const bson_t *node_tags) { uint32_t len; bson_iter_t iter; bson_iter_t sub_iter; const char *key; const char *str; int count; bool node_matches_set; bson_return_val_if_fail(read_tags, -1); bson_return_val_if_fail(node_tags, -1); count = bson_count_keys(read_tags); /* Execute this block if read tags were provided, else bail and return 0 (all nodes equal) */ if (!bson_empty(read_tags) && bson_iter_init(&iter, read_tags)) { /* * Iterate over array of read tag sets provided (each element is a tag set) * Tag sets are provided in order of preference so return the count of the * first set that matches the node or -1 if no set matched the node. */ while (count && bson_iter_next(&iter)) { if (BSON_ITER_HOLDS_DOCUMENT(&iter) && bson_iter_recurse(&iter, &sub_iter)) { node_matches_set = true; /* Iterate over the key/value pairs (tags) in the current set */ while (bson_iter_next(&sub_iter) && BSON_ITER_HOLDS_UTF8(&sub_iter)) { key = bson_iter_key(&sub_iter); str = bson_iter_utf8(&sub_iter, &len); /* If any of the tags do not match, this node cannot satisfy this tag set. */ if (!_contains_tag(node_tags, key, str, len)) { node_matches_set = false; break; } } /* This set matched, return the count as the score */ if (node_matches_set) { return count; } /* Decrement the score and try to match the next set. */ count--; } } return -1; } return 0; }
void ha_replica_set_wait_for_healthy (ha_replica_set_t *replica_set) { bson_iter_t iter; bson_iter_t ar; bson_iter_t member; const char *stateStr; bson_t status; again: sleep(1); if (!ha_replica_set_get_status(replica_set, &status)) { MONGOC_INFO("Failed to get replicaSet status. " "Sleeping 1 second."); goto again; } #if 0 { char *str; str = bson_as_json(&status, NULL); printf("%s\n", str); bson_free(str); } #endif if (!bson_iter_init_find(&iter, &status, "members") || !BSON_ITER_HOLDS_ARRAY(&iter) || !bson_iter_recurse(&iter, &ar)) { bson_destroy(&status); MONGOC_INFO("ReplicaSet has not yet come online. " "Sleeping 1 second."); goto again; } while (bson_iter_next(&ar)) { if (BSON_ITER_HOLDS_DOCUMENT(&ar) && bson_iter_recurse(&ar, &member) && bson_iter_find(&member, "stateStr") && (stateStr = bson_iter_utf8(&member, NULL))) { if (!!strcmp(stateStr, "PRIMARY") && !!strcmp(stateStr, "SECONDARY") && !!strcmp(stateStr, "ARBITER")) { bson_destroy(&status); MONGOC_INFO("Found unhealthy node. Sleeping 1 second."); goto again; } } } bson_destroy(&status); }
int32_t _mongoc_write_result_merge_arrays (uint32_t offset, mongoc_write_result_t *result, /* IN */ bson_t *dest, /* IN */ bson_iter_t *iter) /* IN */ { const bson_value_t *value; bson_iter_t ar; bson_iter_t citer; int32_t idx; int32_t count = 0; int32_t aridx; bson_t child; const char *keyptr = NULL; char key[12]; int len; ENTRY; BSON_ASSERT (result); BSON_ASSERT (dest); BSON_ASSERT (iter); BSON_ASSERT (BSON_ITER_HOLDS_ARRAY (iter)); aridx = bson_count_keys (dest); if (bson_iter_recurse (iter, &ar)) { while (bson_iter_next (&ar)) { if (BSON_ITER_HOLDS_DOCUMENT (&ar) && bson_iter_recurse (&ar, &citer)) { len = (int) bson_uint32_to_string (aridx++, &keyptr, key, sizeof key); bson_append_document_begin (dest, keyptr, len, &child); while (bson_iter_next (&citer)) { if (BSON_ITER_IS_KEY (&citer, "index")) { idx = bson_iter_int32 (&citer) + offset; BSON_APPEND_INT32 (&child, "index", idx); } else { value = bson_iter_value (&citer); BSON_APPEND_VALUE (&child, bson_iter_key (&citer), value); } } bson_append_document_end (dest, &child); count++; } } } RETURN (count); }
void mongoc_apm_command_started_init (mongoc_apm_command_started_t *event, const bson_t *command, const char *database_name, const char *command_name, int64_t request_id, int64_t operation_id, const mongoc_host_list_t *host, uint32_t server_id, void *context) { bson_iter_t iter; uint32_t len; const uint8_t *data; /* Command Monitoring Spec: * * In cases where queries or commands are embedded in a $query parameter * when a read preference is provided, they MUST be unwrapped and the value * of the $query attribute becomes the filter or the command in the started * event. The read preference will subsequently be dropped as it is * considered metadata and metadata is not currently provided in the command * events. */ if (bson_has_field (command, "$readPreference")) { if (bson_iter_init_find (&iter, command, "$query") && BSON_ITER_HOLDS_DOCUMENT (&iter)) { bson_iter_document (&iter, &len, &data); event->command = bson_new_from_data (data, len); event->command_owned = true; } else { /* Got $readPreference without $query, probably OP_MSG */ event->command = (bson_t *) command; event->command_owned = false; } } else { /* discard "const", we promise not to modify "command" */ event->command = (bson_t *) command; event->command_owned = false; } event->database_name = database_name; event->command_name = command_name; event->request_id = request_id; event->operation_id = operation_id; event->host = host; event->server_id = server_id; event->context = context; }
int get_column_map (bson_t *bson_schema, const char *table_name, column_map_t **column_map, int *column_map_size) { bson_iter_t iter_col, iter_dup; int size; column_map_t *column_map_p; const char *data_type; data_type_map_t *data_type_map_p; bson_find_create_table (bson_schema, table_name, &iter_col) || DIE; for (iter_dup = iter_col, size = 0; bson_iter_next (&iter_dup); size++) ; *column_map = calloc (sizeof (column_map_t), size); *column_map_size = size; column_map_p = *column_map; while (bson_iter_next (&iter_col)) { bson_iter_t iter_col_prop; BSON_ITER_HOLDS_DOCUMENT (&iter_col) || DIE; bson_iter_recurse (&iter_col, &iter_col_prop) || DIE; bson_iter_find (&iter_col_prop, "column_name") || DIE; BSON_ITER_HOLDS_UTF8 (&iter_col_prop) || DIE; column_map_p->column_name = bson_iter_dup_utf8 (&iter_col_prop, NULL); bson_iter_find (&iter_col_prop, "data_type") || DIE; BSON_ITER_HOLDS_UTF8 (&iter_col_prop) || DIE; data_type = bson_iter_utf8 (&iter_col_prop, NULL); column_map_p->data_type = data_type; for (data_type_map_p = data_type_map; data_type_map_p < (data_type_map + sizeof (data_type_map)) && strcmp (data_type_map_p->data_type, data_type) != 0; data_type_map_p++) ; if (data_type_map < (data_type_map + sizeof (data_type_map))) column_map_p->bson_append_from_s = data_type_map_p->bson_append_from_s ? data_type_map_p->bson_append_from_s : bson_append_utf8_from_s; else DIE; column_map_p++; } return true; }
static void hippo_cursor_rewind(MongoDBDriverCursorData* data) { if (data->next_after_rewind != 0) { if (data->zchild_active) { throw MongoDriver::Utils::throwLogicException("Cursors cannot rewind after starting iteration"); } else { /* If we're not active, image we're now have fully iterated */ throw MongoDriver::Utils::throwLogicException("Cursors cannot yield multiple iterators"); } } invalidate_current(data); data->current = 0; data->zchild_active = false; if (data->first_batch) { if (data->is_command_cursor) { if (!bson_iter_init(&data->first_batch_iter, data->first_batch)) { return; } if (bson_iter_next(&data->first_batch_iter)) { if (BSON_ITER_HOLDS_DOCUMENT(&data->first_batch_iter)) { const uint8_t *document = NULL; uint32_t document_len = 0; Variant v; bson_iter_document(&data->first_batch_iter, &document_len, &document); BsonToVariantConverter convertor(document, document_len, data->bson_options); convertor.convert(&v); data->zchild_active = true; data->zchild = v; } } } else { Variant v; BsonToVariantConverter convertor(bson_get_data(data->first_batch), data->first_batch->len, data->bson_options); convertor.convert(&v); data->zchild_active = true; data->zchild = v; } } }
bson_bool_t _mongoc_cursor_cursorid_next (mongoc_cursor_t *cursor, const bson_t **bson) { bson_bool_t ret; mongoc_cursor_cursorid_t *cid; bson_iter_t iter; bson_iter_t child; const char *ns; ENTRY; cid = cursor->interface_data; ret = _mongoc_cursor_next (cursor, bson); if (!cid->has_cursor) { cid->has_cursor = TRUE; if (ret && bson_iter_init_find (&iter, *bson, "cursor") && BSON_ITER_HOLDS_DOCUMENT (&iter) && bson_iter_recurse (&iter, &child)) { while (bson_iter_next (&child)) { if (strcmp (bson_iter_key (&child), "id") == 0) { cursor->rpc.reply.cursor_id = bson_iter_int64 (&child); } else if (strcmp (bson_iter_key (&child), "ns") == 0) { ns = bson_iter_utf8 (&child, &cursor->nslen); strncpy (cursor->ns, ns, sizeof cursor->ns - 1); } } cursor->is_command = FALSE; ret = _mongoc_cursor_next (cursor, bson); } } RETURN (ret); }
int monary_load_document_value(const bson_iter_t* bsonit, monary_column_item* citem, int idx) { uint32_t document_len; // The length of document in bytes. const uint8_t* document; // Pointer to the immutable document buffer. uint8_t* dest; if (BSON_ITER_HOLDS_DOCUMENT(bsonit)) { bson_iter_document(bsonit, &document_len, &document); if (document_len > citem->type_arg) { document_len = citem->type_arg; } dest = ((uint8_t*) citem->storage) + (idx * document_len); memcpy(dest, document, document_len); return 1; } else { return 0; } }
SEXP ConvertValue(bson_iter_t* iter){ if(BSON_ITER_HOLDS_INT32(iter)){ return ScalarInteger(bson_iter_int32(iter)); } else if(BSON_ITER_HOLDS_NULL(iter)){ return R_NilValue; } else if(BSON_ITER_HOLDS_BOOL(iter)){ return ScalarLogical(bson_iter_bool(iter)); } else if(BSON_ITER_HOLDS_DOUBLE(iter)){ return ScalarReal(bson_iter_double(iter)); } else if(BSON_ITER_HOLDS_INT64(iter)){ return ScalarReal((double) bson_iter_int64(iter)); } else if(BSON_ITER_HOLDS_UTF8(iter)){ return mkStringUTF8(bson_iter_utf8(iter, NULL)); } else if(BSON_ITER_HOLDS_CODE(iter)){ return mkStringUTF8(bson_iter_code(iter, NULL)); } else if(BSON_ITER_HOLDS_BINARY(iter)){ return ConvertBinary(iter); } else if(BSON_ITER_HOLDS_DATE_TIME(iter)){ return ConvertDate(iter); } else if(BSON_ITER_HOLDS_OID(iter)){ const bson_oid_t *val = bson_iter_oid(iter); char str[25]; bson_oid_to_string(val, str); return mkString(str); } else if(BSON_ITER_HOLDS_ARRAY(iter)){ bson_iter_t child1; bson_iter_t child2; bson_iter_recurse (iter, &child1); bson_iter_recurse (iter, &child2); return ConvertArray(&child1, &child2); } else if(BSON_ITER_HOLDS_DOCUMENT(iter)){ bson_iter_t child1; bson_iter_t child2; bson_iter_recurse (iter, &child1); bson_iter_recurse (iter, &child2); return ConvertObject(&child1, &child2); } else { stop("Unimplemented BSON type %d\n", bson_iter_type(iter)); } }
static request_t * _check_op_query (mock_server_t *server, test_collection_find_with_opts_t *test_data) { mongoc_query_flags_t flags; request_t *request; const bson_t *doc; bson_iter_t iter; uint32_t len; const uint8_t *data; bson_t query; /* Server Selection Spec: all queries to standalone set slaveOk. */ flags = test_data->expected_flags | MONGOC_QUERY_SLAVE_OK; request = mock_server_receives_query ( server, "db.collection", flags, test_data->expected_skip, test_data->expected_n_return, test_data->expected_op_query, test_data->expected_op_query_projection); ASSERT (request); /* check that nothing unexpected is in $query */ if (bson_empty (test_data->filter_bson)) { doc = request_get_doc (request, 0); if (bson_iter_init_find (&iter, doc, "$query")) { ASSERT (BSON_ITER_HOLDS_DOCUMENT (&iter)); bson_iter_document (&iter, &len, &data); bson_init_static (&query, data, (size_t) len); ASSERT (bson_empty (&query)); } } return request; }
bool mongoc_uri_get_mechanism_properties (const mongoc_uri_t *uri, bson_t *properties) { bson_iter_t iter; if (!uri) { return false; } if (bson_iter_init_find_case (&iter, &uri->credentials, "mechanismProperties") && BSON_ITER_HOLDS_DOCUMENT (&iter)) { uint32_t len = 0; const uint8_t *data = NULL; bson_iter_document (&iter, &len, &data); bson_init_static (properties, data, len); return true; } return false; }
static void _mongoc_cursor_cursorid_read_from_batch (mongoc_cursor_t *cursor, const bson_t **bson) { mongoc_cursor_cursorid_t *cid; const uint8_t *data = NULL; uint32_t data_len = 0; ENTRY; cid = (mongoc_cursor_cursorid_t *)cursor->iface_data; BSON_ASSERT (cid); if (bson_iter_next (&cid->batch_iter) && BSON_ITER_HOLDS_DOCUMENT (&cid->batch_iter)) { bson_iter_document (&cid->batch_iter, &data_len, &data); if (bson_init_static (&cid->current_doc, data, data_len)) { *bson = &cid->current_doc; } } }
SEXP ConvertValue(bson_iter_t* iter){ if(BSON_ITER_HOLDS_INT32(iter)){ return ScalarInteger(bson_iter_int32(iter)); } else if(BSON_ITER_HOLDS_NULL(iter)){ return R_NilValue; } else if(BSON_ITER_HOLDS_BOOL(iter)){ return ScalarLogical(bson_iter_bool(iter)); } else if(BSON_ITER_HOLDS_DOUBLE(iter)){ return ScalarReal(bson_iter_double(iter)); } else if(BSON_ITER_HOLDS_INT64(iter)){ return ScalarReal((double) bson_iter_int64(iter)); } else if(BSON_ITER_HOLDS_UTF8(iter)){ return mkStringUTF8(bson_iter_utf8(iter, NULL)); } else if(BSON_ITER_HOLDS_CODE(iter)){ return mkStringUTF8(bson_iter_code(iter, NULL)); } else if(BSON_ITER_HOLDS_BINARY(iter)){ return ConvertBinary(iter); } else if(BSON_ITER_HOLDS_DATE_TIME(iter)){ return ConvertDate(iter); } else if(BSON_ITER_HOLDS_OID(iter)){ //not sure if this casting works return mkRaw((unsigned char *) bson_iter_oid(iter), 12); } else if(BSON_ITER_HOLDS_ARRAY(iter)){ bson_iter_t child1; bson_iter_t child2; bson_iter_recurse (iter, &child1); bson_iter_recurse (iter, &child2); return ConvertArray(&child1, &child2); } else if(BSON_ITER_HOLDS_DOCUMENT(iter)){ bson_iter_t child1; bson_iter_t child2; bson_iter_recurse (iter, &child1); bson_iter_recurse (iter, &child2); return ConvertObject(&child1, &child2); } else { stop("Unimplemented BSON type %d\n", bson_iter_type(iter)); } }
const char * _mongoc_get_command_name (const bson_t *command) { bson_iter_t iter; const char *name; bson_iter_t child; const char *wrapper_name = NULL; BSON_ASSERT (command); if (!bson_iter_init (&iter, command) || !bson_iter_next (&iter)) { return NULL; } name = bson_iter_key (&iter); /* wrapped in "$query" or "query"? * * {$query: {count: "collection"}, $readPreference: {...}} */ if (name[0] == '$') { wrapper_name = "$query"; } else if (!strcmp (name, "query")) { wrapper_name = "query"; } if (wrapper_name && bson_iter_init_find (&iter, command, wrapper_name) && BSON_ITER_HOLDS_DOCUMENT (&iter) && bson_iter_recurse (&iter, &child) && bson_iter_next (&child)) { name = bson_iter_key (&child); } return name; }
/** * _mongoc_parse_wc_err: * @doc: (in): A bson document. * @error: (out): A bson_error_t. * * Parses a document, usually a server reply, * looking for a writeConcernError. Returns true if * there is a writeConcernError, false otherwise. */ bool _mongoc_parse_wc_err (const bson_t *doc, bson_error_t *error) { bson_iter_t iter; bson_iter_t inner; if (bson_iter_init_find(&iter, doc, "writeConcernError") && BSON_ITER_HOLDS_DOCUMENT (&iter)) { const char *errmsg = NULL; int32_t code = 0; bson_iter_recurse(&iter, &inner); while (bson_iter_next(&inner)) { if (BSON_ITER_IS_KEY (&inner, "code")) { code = bson_iter_int32 (&inner); } else if (BSON_ITER_IS_KEY (&inner, "errmsg")) { errmsg = bson_iter_utf8 (&inner, NULL); } } bson_set_error(error, MONGOC_ERROR_WRITE_CONCERN, code, "Write Concern error: %s", errmsg); return true; } return false; }
static void test_get_collection_info (void) { mongoc_database_t *database; mongoc_collection_t *collection; mongoc_client_t *client; bson_error_t error = { 0 }; bson_iter_t iter; bson_iter_t col_array; bson_iter_t col_iter; bson_t capped_options = BSON_INITIALIZER; bson_t autoindexid_options = BSON_INITIALIZER; bson_t noopts_options = BSON_INITIALIZER; bson_t name_filter = BSON_INITIALIZER; int r; int num_infos = 0; bson_t *infos = NULL; const char *name; char *dbname; char *capped_name; char *autoindexid_name; char *noopts_name; client = mongoc_client_new (gTestUri); assert (client); dbname = gen_collection_name ("dbtest"); database = mongoc_client_get_database (client, dbname); assert (database); bson_free (dbname); capped_name = gen_collection_name ("capped"); BSON_APPEND_BOOL (&capped_options, "capped", true); BSON_APPEND_INT32 (&capped_options, "size", 10000000); BSON_APPEND_INT32 (&capped_options, "max", 1024); autoindexid_name = gen_collection_name ("autoindexid"); BSON_APPEND_BOOL (&autoindexid_options, "autoIndexId", false); noopts_name = gen_collection_name ("noopts"); collection = mongoc_database_create_collection (database, capped_name, &capped_options, &error); assert (collection); mongoc_collection_destroy (collection); collection = mongoc_database_create_collection (database, autoindexid_name, &autoindexid_options, &error); assert (collection); mongoc_collection_destroy (collection); collection = mongoc_database_create_collection (database, noopts_name, &noopts_options, &error); assert (collection); mongoc_collection_destroy (collection); /* first we filter on collection name. */ BSON_APPEND_UTF8 (&name_filter, "name", noopts_name); /* We only test with filters since get_collection_names will * test w/o filters for us. */ /* Filter on an exact match of name */ infos = mongoc_database_get_collection_info (database, &name_filter, &error); assert (infos); assert (!error.domain); assert (!error.code); if (bson_iter_init_find (&iter, infos, "collections") && BSON_ITER_HOLDS_ARRAY (&iter) && bson_iter_recurse (&iter, &col_array)) { while (bson_iter_next (&col_array)) { if (BSON_ITER_HOLDS_DOCUMENT (&col_array) && bson_iter_recurse (&col_array, &col_iter) && bson_iter_find (&col_iter, "name") && BSON_ITER_HOLDS_UTF8 (&col_iter) && (name = bson_iter_utf8 (&col_iter, NULL))) { ++num_infos; assert (0 == strcmp (name, noopts_name)); } else { assert (false); } } } assert (1 == num_infos); num_infos = 0; bson_destroy (infos); infos = NULL; r = mongoc_database_drop (database, &error); assert (r); assert (!error.domain); assert (!error.code); bson_free (capped_name); bson_free (noopts_name); bson_free (autoindexid_name); mongoc_database_destroy (database); mongoc_client_destroy (client); }
mongoc_collection_t * mongoc_database_create_collection (mongoc_database_t *database, const char *name, const bson_t *options, bson_error_t *error) { mongoc_collection_t *collection = NULL; bson_iter_t iter; bson_t cmd; bool capped = false; bson_return_val_if_fail (database, NULL); bson_return_val_if_fail (name, NULL); if (strchr (name, '$')) { bson_set_error (error, MONGOC_ERROR_NAMESPACE, MONGOC_ERROR_NAMESPACE_INVALID, "The namespace \"%s\" is invalid.", name); return NULL; } if (options) { if (bson_iter_init_find (&iter, options, "capped")) { if (!BSON_ITER_HOLDS_BOOL (&iter)) { bson_set_error (error, MONGOC_ERROR_COMMAND, MONGOC_ERROR_COMMAND_INVALID_ARG, "The argument \"capped\" must be a boolean."); return NULL; } capped = bson_iter_bool (&iter); } if (bson_iter_init_find (&iter, options, "autoIndexId") && !BSON_ITER_HOLDS_BOOL (&iter)) { bson_set_error (error, MONGOC_ERROR_COMMAND, MONGOC_ERROR_COMMAND_INVALID_ARG, "The argument \"autoIndexId\" must be a boolean."); return NULL; } if (bson_iter_init_find (&iter, options, "size")) { if (!BSON_ITER_HOLDS_INT32 (&iter) && !BSON_ITER_HOLDS_INT64 (&iter)) { bson_set_error (error, MONGOC_ERROR_COMMAND, MONGOC_ERROR_COMMAND_INVALID_ARG, "The argument \"size\" must be an integer."); return NULL; } if (!capped) { bson_set_error (error, MONGOC_ERROR_COMMAND, MONGOC_ERROR_COMMAND_INVALID_ARG, "The \"size\" parameter requires {\"capped\": true}"); return NULL; } } if (bson_iter_init_find (&iter, options, "max")) { if (!BSON_ITER_HOLDS_INT32 (&iter) && !BSON_ITER_HOLDS_INT64 (&iter)) { bson_set_error (error, MONGOC_ERROR_COMMAND, MONGOC_ERROR_COMMAND_INVALID_ARG, "The argument \"max\" must be an integer."); return NULL; } if (!capped) { bson_set_error (error, MONGOC_ERROR_COMMAND, MONGOC_ERROR_COMMAND_INVALID_ARG, "The \"size\" parameter requires {\"capped\": true}"); return NULL; } } if (bson_iter_init_find (&iter, options, "storage")) { if (!BSON_ITER_HOLDS_DOCUMENT (&iter)) { bson_set_error (error, MONGOC_ERROR_COMMAND, MONGOC_ERROR_COMMAND_INVALID_ARG, "The \"storage\" parameter must be a document"); return NULL; } if (bson_iter_find (&iter, "wiredtiger")) { if (!BSON_ITER_HOLDS_DOCUMENT (&iter)) { bson_set_error (error, MONGOC_ERROR_COMMAND, MONGOC_ERROR_COMMAND_INVALID_ARG, "The \"wiredtiger\" option must take a document argument with a \"configString\" field"); return NULL; } if (bson_iter_find (&iter, "configString")) { if (!BSON_ITER_HOLDS_UTF8 (&iter)) { bson_set_error (error, MONGOC_ERROR_COMMAND, MONGOC_ERROR_COMMAND_INVALID_ARG, "The \"configString\" parameter must be a string"); return NULL; } } else { bson_set_error (error, MONGOC_ERROR_COMMAND, MONGOC_ERROR_COMMAND_INVALID_ARG, "The \"wiredtiger\" option must take a document argument with a \"configString\" field"); return NULL; } } } } bson_init (&cmd); BSON_APPEND_UTF8 (&cmd, "create", name); if (options) { if (!bson_iter_init (&iter, options)) { bson_set_error (error, MONGOC_ERROR_COMMAND, MONGOC_ERROR_COMMAND_INVALID_ARG, "The argument \"options\" is corrupt or invalid."); bson_destroy (&cmd); return NULL; } while (bson_iter_next (&iter)) { if (!bson_append_iter (&cmd, bson_iter_key (&iter), -1, &iter)) { bson_set_error (error, MONGOC_ERROR_COMMAND, MONGOC_ERROR_COMMAND_INVALID_ARG, "Failed to append \"options\" to create command."); bson_destroy (&cmd); return NULL; } } } if (mongoc_database_command_simple (database, &cmd, NULL, NULL, error)) { collection = _mongoc_collection_new (database->client, database->name, name, database->read_prefs, database->write_concern); } bson_destroy (&cmd); return collection; }
static void _mongoc_write_command(mongoc_write_command_t *command, mongoc_client_t *client, mongoc_server_stream_t *server_stream, const char *database, const char *collection, const mongoc_write_concern_t *write_concern, uint32_t offset, mongoc_write_result_t *result, bson_error_t *error) { const uint8_t *data; bson_iter_t iter; const char *key; uint32_t len = 0; bson_t tmp; bson_t ar; bson_t cmd; bson_t reply; char str [16]; bool has_more; bool ret = false; uint32_t i; int32_t max_bson_obj_size; int32_t max_write_batch_size; int32_t min_wire_version; uint32_t key_len; ENTRY; BSON_ASSERT (command); BSON_ASSERT (client); BSON_ASSERT (database); BSON_ASSERT (server_stream); BSON_ASSERT (collection); max_bson_obj_size = mongoc_server_stream_max_bson_obj_size (server_stream); max_write_batch_size = mongoc_server_stream_max_write_batch_size (server_stream); /* * If we have an unacknowledged write and the server supports the legacy * opcodes, then submit the legacy opcode so we don't need to wait for * a response from the server. */ min_wire_version = server_stream->sd->min_wire_version; if ((min_wire_version == 0) && !_mongoc_write_concern_needs_gle (write_concern)) { if (command->flags.bypass_document_validation != MONGOC_BYPASS_DOCUMENT_VALIDATION_DEFAULT) { bson_set_error (error, MONGOC_ERROR_COMMAND, MONGOC_ERROR_COMMAND_INVALID_ARG, "Cannot set bypassDocumentValidation for unacknowledged writes"); EXIT; } gLegacyWriteOps[command->type] (command, client, server_stream, database, collection, write_concern, offset, result, error); EXIT; } if (!command->n_documents || !bson_iter_init (&iter, command->documents) || !bson_iter_next (&iter)) { _empty_error (command, error); result->failed = true; EXIT; } again: bson_init (&cmd); has_more = false; i = 0; BSON_APPEND_UTF8 (&cmd, gCommandNames[command->type], collection); BSON_APPEND_DOCUMENT (&cmd, "writeConcern", WRITE_CONCERN_DOC (write_concern)); BSON_APPEND_BOOL (&cmd, "ordered", command->flags.ordered); if (command->flags.bypass_document_validation != MONGOC_BYPASS_DOCUMENT_VALIDATION_DEFAULT) { BSON_APPEND_BOOL (&cmd, "bypassDocumentValidation", !!command->flags.bypass_document_validation); } if (!_mongoc_write_command_will_overflow (0, command->documents->len, command->n_documents, max_bson_obj_size, max_write_batch_size)) { /* copy the whole documents buffer as e.g. "updates": [...] */ BSON_APPEND_ARRAY (&cmd, gCommandFields[command->type], command->documents); i = command->n_documents; } else { bson_append_array_begin (&cmd, gCommandFields[command->type], -1, &ar); do { if (!BSON_ITER_HOLDS_DOCUMENT (&iter)) { BSON_ASSERT (false); } bson_iter_document (&iter, &len, &data); key_len = (uint32_t) bson_uint32_to_string (i, &key, str, sizeof str); if (_mongoc_write_command_will_overflow (ar.len, key_len + len + 2, i, max_bson_obj_size, max_write_batch_size)) { has_more = true; break; } if (!bson_init_static (&tmp, data, len)) { BSON_ASSERT (false); } BSON_APPEND_DOCUMENT (&ar, key, &tmp); bson_destroy (&tmp); i++; } while (bson_iter_next (&iter)); bson_append_array_end (&cmd, &ar); } if (!i) { too_large_error (error, i, len, max_bson_obj_size, NULL); result->failed = true; ret = false; } else { ret = mongoc_cluster_run_command (&client->cluster, server_stream->stream, MONGOC_QUERY_NONE, database, &cmd, &reply, error); if (!ret) { result->failed = true; } _mongoc_write_result_merge (result, command, &reply, offset); offset += i; bson_destroy (&reply); } bson_destroy (&cmd); if (has_more && (ret || !command->flags.ordered)) { GOTO (again); } EXIT; }
void _mongoc_write_result_merge (mongoc_write_result_t *result, /* IN */ mongoc_write_command_t *command, /* IN */ const bson_t *reply, /* IN */ uint32_t offset) { int32_t server_index = 0; const bson_value_t *value; bson_iter_t iter; bson_iter_t citer; bson_iter_t ar; int32_t n_upserted = 0; int32_t affected = 0; ENTRY; BSON_ASSERT (result); BSON_ASSERT (reply); if (bson_iter_init_find (&iter, reply, "n") && BSON_ITER_HOLDS_INT32 (&iter)) { affected = bson_iter_int32 (&iter); } if (bson_iter_init_find (&iter, reply, "writeErrors") && BSON_ITER_HOLDS_ARRAY (&iter) && bson_iter_recurse (&iter, &citer) && bson_iter_next (&citer)) { result->failed = true; } switch (command->type) { case MONGOC_WRITE_COMMAND_INSERT: result->nInserted += affected; break; case MONGOC_WRITE_COMMAND_DELETE: result->nRemoved += affected; break; case MONGOC_WRITE_COMMAND_UPDATE: /* server returns each upserted _id with its index into this batch * look for "upserted": [{"index": 4, "_id": ObjectId()}, ...] */ if (bson_iter_init_find (&iter, reply, "upserted")) { if (BSON_ITER_HOLDS_ARRAY (&iter) && (bson_iter_recurse (&iter, &ar))) { while (bson_iter_next (&ar)) { if (BSON_ITER_HOLDS_DOCUMENT (&ar) && bson_iter_recurse (&ar, &citer) && bson_iter_find (&citer, "index") && BSON_ITER_HOLDS_INT32 (&citer)) { server_index = bson_iter_int32 (&citer); if (bson_iter_recurse (&ar, &citer) && bson_iter_find (&citer, "_id")) { value = bson_iter_value (&citer); _mongoc_write_result_append_upsert ( result, offset + server_index, value); n_upserted++; } } } } result->nUpserted += n_upserted; /* * XXX: The following addition to nMatched needs some checking. * I'm highly skeptical of it. */ result->nMatched += BSON_MAX (0, (affected - n_upserted)); } else { result->nMatched += affected; } if (bson_iter_init_find (&iter, reply, "nModified") && BSON_ITER_HOLDS_INT32 (&iter)) { result->nModified += bson_iter_int32 (&iter); } break; default: BSON_ASSERT (false); break; } if (bson_iter_init_find (&iter, reply, "writeErrors") && BSON_ITER_HOLDS_ARRAY (&iter)) { _mongoc_write_result_merge_arrays ( offset, result, &result->writeErrors, &iter); } if (bson_iter_init_find (&iter, reply, "writeConcernError") && BSON_ITER_HOLDS_DOCUMENT (&iter)) { uint32_t len; const uint8_t *data; bson_t write_concern_error; char str[16]; const char *key; /* writeConcernError is a subdocument in the server response * append it to the result->writeConcernErrors array */ bson_iter_document (&iter, &len, &data); bson_init_static (&write_concern_error, data, len); bson_uint32_to_string ( result->n_writeConcernErrors, &key, str, sizeof str); if (!bson_append_document ( &result->writeConcernErrors, key, -1, &write_concern_error)) { MONGOC_ERROR ("Error adding \"%s\" to writeConcernErrors.\n", key); } result->n_writeConcernErrors++; } /* inefficient if there are ever large numbers: for each label in each err, * we linear-search result->errorLabels to see if it's included yet */ _mongoc_bson_array_copy_labels_to (reply, &result->errorLabels); EXIT; }
static mongoc_matcher_op_t * _mongoc_matcher_parse_logical (mongoc_matcher_opcode_t opcode, /* IN */ bson_iter_t *iter, /* IN */ bool is_root, /* IN */ bson_error_t *error) /* OUT */ { mongoc_matcher_op_t *left; mongoc_matcher_op_t *right; mongoc_matcher_op_t *more; mongoc_matcher_op_t *more_wrap; bson_iter_t child; BSON_ASSERT (opcode); BSON_ASSERT (iter); BSON_ASSERT (iter); if (!bson_iter_next (iter)) { bson_set_error (error, MONGOC_ERROR_MATCHER, MONGOC_ERROR_MATCHER_INVALID, "Invalid logical operator."); return NULL; } if (is_root) { if (!(left = _mongoc_matcher_parse (iter, error))) { return NULL; } } else { if (!BSON_ITER_HOLDS_DOCUMENT (iter)) { bson_set_error (error, MONGOC_ERROR_MATCHER, MONGOC_ERROR_MATCHER_INVALID, "Expected document in value."); return NULL; } bson_iter_recurse (iter, &child); bson_iter_next (&child); if (!(left = _mongoc_matcher_parse (&child, error))) { return NULL; } } if (!bson_iter_next (iter)) { return left; } if (is_root) { if (!(right = _mongoc_matcher_parse (iter, error))) { return NULL; } } else { if (!BSON_ITER_HOLDS_DOCUMENT (iter)) { bson_set_error (error, MONGOC_ERROR_MATCHER, MONGOC_ERROR_MATCHER_INVALID, "Expected document in value."); return NULL; } bson_iter_recurse (iter, &child); bson_iter_next (&child); if (!(right = _mongoc_matcher_parse (&child, error))) { return NULL; } } more = _mongoc_matcher_parse_logical (opcode, iter, is_root, error); if (more) { more_wrap = _mongoc_matcher_op_logical_new (opcode, right, more); return _mongoc_matcher_op_logical_new (opcode, left, more_wrap); } return _mongoc_matcher_op_logical_new (opcode, left, right); }
static void test_find_and_modify (void) { mongoc_collection_t *collection; mongoc_client_t *client; bson_error_t error; bson_iter_t iter; bson_iter_t citer; bson_t *update; bson_t doc = BSON_INITIALIZER; bson_t reply; mongoc_find_and_modify_opts_t *opts; client = test_framework_client_new (); ASSERT (client); collection = get_test_collection (client, "test_find_and_modify"); ASSERT (collection); BSON_APPEND_INT32 (&doc, "superduper", 77889); ASSERT_OR_PRINT (mongoc_collection_insert ( collection, MONGOC_INSERT_NONE, &doc, NULL, &error), error); update = BCON_NEW ("$set", "{", "superduper", BCON_INT32 (1234), "}"); opts = mongoc_find_and_modify_opts_new (); mongoc_find_and_modify_opts_set_update (opts, update); mongoc_find_and_modify_opts_set_fields (opts, tmp_bson ("{'superduper': 1}")); mongoc_find_and_modify_opts_set_sort (opts, tmp_bson ("{'superduper': 1}")); mongoc_find_and_modify_opts_set_flags (opts, MONGOC_FIND_AND_MODIFY_RETURN_NEW); ASSERT_OR_PRINT (mongoc_collection_find_and_modify_with_opts ( collection, &doc, opts, &reply, &error), error); assert (bson_iter_init_find (&iter, &reply, "value")); assert (BSON_ITER_HOLDS_DOCUMENT (&iter)); assert (bson_iter_recurse (&iter, &citer)); assert (bson_iter_find (&citer, "superduper")); assert (BSON_ITER_HOLDS_INT32 (&citer)); assert (bson_iter_int32 (&citer) == 1234); assert (bson_iter_init_find (&iter, &reply, "lastErrorObject")); assert (BSON_ITER_HOLDS_DOCUMENT (&iter)); assert (bson_iter_recurse (&iter, &citer)); assert (bson_iter_find (&citer, "updatedExisting")); assert (BSON_ITER_HOLDS_BOOL (&citer)); assert (bson_iter_bool (&citer)); bson_destroy (&reply); bson_destroy (update); ASSERT_OR_PRINT (mongoc_collection_drop (collection, &error), error); mongoc_find_and_modify_opts_destroy (opts); mongoc_collection_destroy (collection); mongoc_client_destroy (client); bson_destroy (&doc); }
/** * _mongoc_gridfs_file_new_from_bson: * * creates a gridfs file from a bson object * * This is only really useful for instantiating a gridfs file from a server * side object */ mongoc_gridfs_file_t * _mongoc_gridfs_file_new_from_bson (mongoc_gridfs_t *gridfs, const bson_t *data) { mongoc_gridfs_file_t *file; const bson_value_t *value; const char *key; bson_iter_t iter; const uint8_t *buf; uint32_t buf_len; ENTRY; BSON_ASSERT (gridfs); BSON_ASSERT (data); file = (mongoc_gridfs_file_t *)bson_malloc0 (sizeof *file); file->gridfs = gridfs; bson_copy_to (data, &file->bson); bson_iter_init (&iter, &file->bson); while (bson_iter_next (&iter)) { key = bson_iter_key (&iter); if (0 == strcmp (key, "_id")) { value = bson_iter_value (&iter); bson_value_copy (value, &file->files_id); } else if (0 == strcmp (key, "length")) { if (!BSON_ITER_HOLDS_INT32 (&iter) && !BSON_ITER_HOLDS_INT64 (&iter) && !BSON_ITER_HOLDS_DOUBLE (&iter)) { GOTO (failure); } file->length = bson_iter_as_int64 (&iter); } else if (0 == strcmp (key, "chunkSize")) { if (!BSON_ITER_HOLDS_INT32 (&iter) && !BSON_ITER_HOLDS_INT64 (&iter) && !BSON_ITER_HOLDS_DOUBLE (&iter)) { GOTO (failure); } if (bson_iter_as_int64 (&iter) > INT32_MAX) { GOTO (failure); } file->chunk_size = (int32_t)bson_iter_as_int64 (&iter); } else if (0 == strcmp (key, "uploadDate")) { if (!BSON_ITER_HOLDS_DATE_TIME (&iter)){ GOTO (failure); } file->upload_date = bson_iter_date_time (&iter); } else if (0 == strcmp (key, "md5")) { if (!BSON_ITER_HOLDS_UTF8 (&iter)) { GOTO (failure); } file->bson_md5 = bson_iter_utf8 (&iter, NULL); } else if (0 == strcmp (key, "filename")) { if (!BSON_ITER_HOLDS_UTF8 (&iter)) { GOTO (failure); } file->bson_filename = bson_iter_utf8 (&iter, NULL); } else if (0 == strcmp (key, "contentType")) { if (!BSON_ITER_HOLDS_UTF8 (&iter)) { GOTO (failure); } file->bson_content_type = bson_iter_utf8 (&iter, NULL); } else if (0 == strcmp (key, "aliases")) { if (!BSON_ITER_HOLDS_ARRAY (&iter)) { GOTO (failure); } bson_iter_array (&iter, &buf_len, &buf); bson_init_static (&file->bson_aliases, buf, buf_len); } else if (0 == strcmp (key, "metadata")) { if (!BSON_ITER_HOLDS_DOCUMENT (&iter)) { GOTO (failure); } bson_iter_document (&iter, &buf_len, &buf); bson_init_static (&file->bson_metadata, buf, buf_len); } } /* TODO: is there are a minimal object we should be verifying that we * actually have here? */ RETURN (file); failure: bson_destroy (&file->bson); RETURN (NULL); }