Skip to content

Commit dbb2584

Browse files
committed
CDRIVER-991: findAndModify + WriteConcernError should populate error
1 parent 60f5569 commit dbb2584

File tree

2 files changed

+90
-1
lines changed

2 files changed

+90
-1
lines changed

src/mongoc/mongoc-collection.c

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2091,7 +2091,10 @@ mongoc_collection_find_and_modify_with_opts (mongoc_collection_t
20912091
{
20922092
mongoc_cluster_t *cluster;
20932093
mongoc_server_stream_t *server_stream;
2094+
bson_iter_t iter;
2095+
bson_iter_t inner;
20942096
const char *name;
2097+
bson_t reply_local;
20952098
bool ret;
20962099
bson_t command = BSON_INITIALIZER;
20972100

@@ -2159,8 +2162,28 @@ mongoc_collection_find_and_modify_with_opts (mongoc_collection_t
21592162

21602163
ret = mongoc_cluster_run_command (cluster, server_stream->stream,
21612164
MONGOC_QUERY_NONE, collection->db,
2162-
&command, reply, error);
2165+
&command, &reply_local, error);
2166+
2167+
if (bson_iter_init_find (&iter, &reply_local, "writeConcernError") &&
2168+
BSON_ITER_HOLDS_DOCUMENT (&iter)) {
2169+
const char *errmsg = NULL;
2170+
int32_t code = 0;
2171+
2172+
bson_iter_recurse(&iter, &inner);
2173+
while (bson_iter_next (&inner)) {
2174+
if (BSON_ITER_IS_KEY (&inner, "code")) {
2175+
code = bson_iter_int32 (&inner);
2176+
} else if (BSON_ITER_IS_KEY (&inner, "errmsg")) {
2177+
errmsg = bson_iter_utf8 (&inner, NULL);
2178+
}
2179+
}
2180+
bson_set_error (error, MONGOC_ERROR_WRITE_CONCERN, code, "Write Concern error: %s", errmsg);
2181+
}
2182+
if (reply) {
2183+
bson_copy_to (&reply_local, reply);
2184+
}
21632185

2186+
bson_destroy (&reply_local);
21642187
bson_destroy (&command);
21652188
mongoc_server_stream_cleanup (server_stream);
21662189

tests/test-mongoc-find-and-modify.c

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,16 @@ auto_ismaster (mock_server_t *server,
3232
bson_free (response);
3333
}
3434

35+
36+
int
37+
should_run_fam_wc (void)
38+
{
39+
if (test_framework_is_replset()) {
40+
return test_framework_max_wire_version_at_least (WIRE_VERSION_FAM_WRITE_CONCERN);
41+
}
42+
return 0;
43+
}
44+
3545
static mongoc_collection_t *
3646
get_test_collection (mongoc_client_t *client,
3747
const char *prefix)
@@ -211,6 +221,59 @@ test_find_and_modify_write_concern (int wire_version)
211221
bson_destroy (&doc);
212222
}
213223

224+
static void
225+
test_find_and_modify_write_concern_wire_32_failure (void *context)
226+
{
227+
mongoc_collection_t *collection;
228+
mongoc_client_t *client;
229+
bson_error_t error;
230+
mongoc_find_and_modify_opts_t *opts;
231+
bson_t reply;
232+
bson_t query = BSON_INITIALIZER;
233+
bson_t *update;
234+
bool success;
235+
mongoc_write_concern_t *wc;
236+
237+
client = test_framework_client_new ();
238+
collection = get_test_collection (client, "writeFailure");
239+
wc = mongoc_write_concern_new ();
240+
241+
mongoc_write_concern_set_w (wc, 42);
242+
mongoc_collection_set_write_concern (collection, wc);
243+
244+
/* Find Zlatan Ibrahimovic, the striker */
245+
BSON_APPEND_UTF8 (&query, "firstname", "Zlatan");
246+
BSON_APPEND_UTF8 (&query, "lastname", "Ibrahimovic");
247+
BSON_APPEND_UTF8 (&query, "profession", "Football player");
248+
BSON_APPEND_INT32 (&query, "age", 34);
249+
BSON_APPEND_INT32 (&query, "goals", (16+35+23+57+16+14+28+84)+(1+6+62));
250+
251+
/* Add his football position */
252+
update = BCON_NEW ("$set", "{",
253+
"position", BCON_UTF8 ("striker"),
254+
"}");
255+
256+
opts = mongoc_find_and_modify_opts_new ();
257+
258+
mongoc_find_and_modify_opts_set_update (opts, update);
259+
260+
/* Create the document if it didn't exist, and return the updated document */
261+
mongoc_find_and_modify_opts_set_flags (opts, MONGOC_FIND_AND_MODIFY_UPSERT|MONGOC_FIND_AND_MODIFY_RETURN_NEW);
262+
263+
success = mongoc_collection_find_and_modify_with_opts (collection, &query, opts, &reply, &error);
264+
265+
ASSERT (success);
266+
ASSERT_ERROR_CONTAINS (error, MONGOC_ERROR_WRITE_CONCERN, 100, "Write Concern error:");
267+
268+
bson_destroy (&reply);
269+
bson_destroy (update);
270+
bson_destroy (&query);
271+
mongoc_find_and_modify_opts_destroy (opts);
272+
mongoc_collection_drop (collection, NULL);
273+
mongoc_collection_destroy (collection);
274+
mongoc_client_destroy (client);
275+
}
276+
214277
static void
215278
test_find_and_modify_write_concern_wire_32 (void)
216279
{
@@ -303,4 +366,7 @@ test_find_and_modify_install (TestSuite *suite)
303366
test_find_and_modify_write_concern_wire_32);
304367
TestSuite_Add (suite, "/find_and_modify/find_and_modify/write_concern_pre_32",
305368
test_find_and_modify_write_concern_wire_pre_32);
369+
TestSuite_AddFull (suite, "/find_and_modify/find_and_modify/write_concern_failure",
370+
test_find_and_modify_write_concern_wire_32_failure, NULL, NULL,
371+
should_run_fam_wc);
306372
}

0 commit comments

Comments
 (0)