/* * 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); }
/* * 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; }
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); }
/** * _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_index_offset (void) { mongoc_bulk_operation_t *bulk; mongoc_collection_t *collection; mongoc_client_t *client; bson_error_t error; bson_iter_t iter; bson_iter_t ar; bson_iter_t citer; bson_t reply; bson_t *sel; bson_t *doc; bool r; client = mongoc_client_new (gTestUri); assert (client); collection = get_test_collection (client, "test_index_offset"); assert (collection); doc = bson_new (); BSON_APPEND_INT32 (doc, "abcd", 1234); r = mongoc_collection_insert (collection, MONGOC_INSERT_NONE, doc, NULL, &error); assert (r); bson_destroy (doc); bulk = mongoc_collection_create_bulk_operation (collection, true, NULL); assert (bulk); sel = BCON_NEW ("abcd", BCON_INT32 (1234)); doc = BCON_NEW ("$set", "{", "hello", "there", "}"); mongoc_bulk_operation_delete_one (bulk, sel); mongoc_bulk_operation_update (bulk, sel, doc, true); r = mongoc_bulk_operation_execute (bulk, &reply, &error); assert (r); assert (bson_iter_init_find (&iter, &reply, "nUpserted")); assert (BSON_ITER_HOLDS_INT32 (&iter)); assert (bson_iter_int32 (&iter) == 1); assert (bson_iter_init_find (&iter, &reply, "nMatched")); assert (BSON_ITER_HOLDS_INT32 (&iter)); assert (bson_iter_int32 (&iter) == 0); assert (bson_iter_init_find (&iter, &reply, "nRemoved")); assert (BSON_ITER_HOLDS_INT32 (&iter)); assert (bson_iter_int32 (&iter) == 1); assert (bson_iter_init_find (&iter, &reply, "nInserted")); assert (BSON_ITER_HOLDS_INT32 (&iter)); assert (bson_iter_int32 (&iter) == 0); if (bson_iter_init_find (&iter, &reply, "nModified")) { assert (BSON_ITER_HOLDS_INT32 (&iter)); assert (bson_iter_int32 (&iter) == 0); } assert (bson_iter_init_find (&iter, &reply, "upserted")); assert (BSON_ITER_HOLDS_ARRAY (&iter)); assert (bson_iter_recurse (&iter, &ar)); assert (bson_iter_next (&ar)); assert (BSON_ITER_HOLDS_DOCUMENT (&ar)); assert (bson_iter_recurse (&ar, &citer)); assert (bson_iter_next (&citer)); assert (BSON_ITER_IS_KEY (&citer, "index")); assert (bson_iter_int32 (&citer) == 1); assert (bson_iter_next (&citer)); assert (BSON_ITER_IS_KEY (&citer, "_id")); assert (BSON_ITER_HOLDS_OID (&citer)); assert (!bson_iter_next (&citer)); assert (!bson_iter_next (&ar)); assert (bson_iter_init_find (&iter, &reply, "writeErrors")); assert (BSON_ITER_HOLDS_ARRAY (&iter)); assert (bson_iter_recurse (&iter, &ar)); assert (!bson_iter_next (&ar)); bson_destroy (&reply); r = mongoc_collection_drop (collection, &error); assert (r); mongoc_bulk_operation_destroy (bulk); mongoc_collection_destroy (collection); mongoc_client_destroy (client); bson_destroy (doc); bson_destroy (sel); }