Skip to content

Commit ab0606a

Browse files
committed
CDRIVER-2213 findAndModify respects writeConcern opt
1 parent d255a70 commit ab0606a

File tree

5 files changed

+103
-14
lines changed

5 files changed

+103
-14
lines changed

NEWS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
mongo-c-driver 1.8.0
22
====================
33

4+
* mongoc_collection_find_and_modify_with_opts now respects a "writeConcern"
5+
field in the "extra" BSON document in its mongoc_find_and_modify_opts_t.
46
* The command functions mongoc_client_read_write_command_with_opts,
57
mongoc_database_read_write_command_with_opts, and
68
mongoc_collection_read_write_command_with_opts now ignore the "read_prefs"

examples/find_and_modify_with_opts/opts.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ fam_opts (mongoc_collection_t *collection)
77
bson_t *update;
88
bson_error_t error;
99
bson_t query = BSON_INITIALIZER;
10+
mongoc_write_concern_t *wc;
1011
bson_t extra = BSON_INITIALIZER;
1112
bool success;
1213

@@ -25,6 +26,11 @@ fam_opts (mongoc_collection_t *collection)
2526
/* Abort if the operation takes too long. */
2627
mongoc_find_and_modify_opts_set_max_time_ms (opts, 100);
2728

29+
/* Set write concern w: 2 */
30+
wc = mongoc_write_concern_new ();
31+
mongoc_write_concern_set_w (wc, 2);
32+
mongoc_write_concern_append (wc, &extra);
33+
2834
/* Some future findAndModify option the driver doesn't support conveniently
2935
*/
3036
BSON_APPEND_INT32 (&extra, "futureOption", 42);
@@ -48,5 +54,6 @@ fam_opts (mongoc_collection_t *collection)
4854
bson_destroy (&extra);
4955
bson_destroy (update);
5056
bson_destroy (&query);
57+
mongoc_write_concern_destroy (wc);
5158
mongoc_find_and_modify_opts_destroy (opts);
5259
}

src/mongoc/mongoc-cmd.c

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020
#include "mongoc-trace-private.h"
2121
#include "mongoc-client-private.h"
2222
#include "mongoc-write-concern-private.h"
23+
/* For strcasecmp on Windows */
24+
#include "mongoc-util-private.h"
2325

2426

2527
void
@@ -67,11 +69,16 @@ mongoc_cmd_parts_append_opts (mongoc_cmd_parts_t *parts,
6769
int max_wire_version,
6870
bson_error_t *error)
6971
{
72+
bool is_fam;
73+
7074
ENTRY;
7175

7276
/* not yet assembled */
7377
BSON_ASSERT (!parts->assembled.command);
7478

79+
is_fam =
80+
!strcasecmp (_mongoc_get_command_name (parts->body), "findandmodify");
81+
7582
while (bson_iter_next (iter)) {
7683
if (BSON_ITER_IS_KEY (iter, "collation")) {
7784
if (max_wire_version < WIRE_VERSION_COLLATION) {
@@ -91,7 +98,8 @@ mongoc_cmd_parts_append_opts (mongoc_cmd_parts_t *parts,
9198
RETURN (false);
9299
}
93100

94-
if (max_wire_version < WIRE_VERSION_CMD_WRITE_CONCERN) {
101+
if ((is_fam && max_wire_version < WIRE_VERSION_FAM_WRITE_CONCERN) ||
102+
(!is_fam && max_wire_version < WIRE_VERSION_CMD_WRITE_CONCERN)) {
95103
continue;
96104
}
97105

src/mongoc/mongoc-collection.c

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2526,19 +2526,22 @@ mongoc_collection_find_and_modify_with_opts (
25262526
BSON_APPEND_INT32 (&command, "maxTimeMS", opts->max_time_ms);
25272527
}
25282528

2529-
if (server_stream->sd->max_wire_version >= WIRE_VERSION_FAM_WRITE_CONCERN) {
2530-
if (!mongoc_write_concern_is_valid (collection->write_concern)) {
2531-
bson_set_error (error,
2532-
MONGOC_ERROR_COMMAND,
2533-
MONGOC_ERROR_COMMAND_INVALID_ARG,
2534-
"The write concern is invalid.");
2535-
bson_destroy (&command);
2536-
mongoc_server_stream_cleanup (server_stream);
2537-
RETURN (false);
2538-
}
2529+
if (!bson_has_field (&opts->extra, "writeConcern")) {
2530+
if (server_stream->sd->max_wire_version >=
2531+
WIRE_VERSION_FAM_WRITE_CONCERN) {
2532+
if (!mongoc_write_concern_is_valid (collection->write_concern)) {
2533+
bson_set_error (error,
2534+
MONGOC_ERROR_COMMAND,
2535+
MONGOC_ERROR_COMMAND_INVALID_ARG,
2536+
"The write concern is invalid.");
2537+
bson_destroy (&command);
2538+
mongoc_server_stream_cleanup (server_stream);
2539+
RETURN (false);
2540+
}
25392541

2540-
if (mongoc_write_concern_is_acknowledged (collection->write_concern)) {
2541-
_BSON_APPEND_WRITE_CONCERN (&command, collection->write_concern);
2542+
if (mongoc_write_concern_is_acknowledged (collection->write_concern)) {
2543+
_BSON_APPEND_WRITE_CONCERN (&command, collection->write_concern);
2544+
}
25422545
}
25432546
}
25442547

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

Lines changed: 70 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,8 @@ test_find_and_modify_write_concern (int wire_version)
206206
"{ 'findAndModify' : 'test_find_and_modify', "
207207
"'query' : { 'superduper' : 77889 },"
208208
"'update' : { '$set' : { 'superduper' : 1234 } },"
209-
"'new' : true }");
209+
"'new' : true,"
210+
"'writeConcern' : { '$exists': false } }");
210211
}
211212

212213
mock_server_replies_simple (request, "{ 'value' : null, 'ok' : 1 }");
@@ -416,6 +417,71 @@ test_find_and_modify_opts (void)
416417
}
417418

418419

420+
static void
421+
test_find_and_modify_opts_write_concern (void)
422+
{
423+
mongoc_write_concern_t *w2;
424+
mongoc_write_concern_t *w3;
425+
mock_server_t *server;
426+
mongoc_client_t *client;
427+
mongoc_collection_t *collection;
428+
bson_error_t error;
429+
mongoc_find_and_modify_opts_t *opts;
430+
bson_t extra = BSON_INITIALIZER;
431+
future_t *future;
432+
request_t *request;
433+
434+
w2 = mongoc_write_concern_new ();
435+
mongoc_write_concern_set_w (w2, 2);
436+
w3 = mongoc_write_concern_new ();
437+
mongoc_write_concern_set_w (w3, 3);
438+
439+
server = mock_server_with_autoismaster (WIRE_VERSION_FAM_WRITE_CONCERN);
440+
mock_server_run (server);
441+
442+
client = mongoc_client_new_from_uri (mock_server_get_uri (server));
443+
collection = mongoc_client_get_collection (client, "db", "collection");
444+
445+
opts = mongoc_find_and_modify_opts_new ();
446+
mongoc_write_concern_append (w2, &extra);
447+
BSON_ASSERT (mongoc_find_and_modify_opts_append (opts, &extra));
448+
bson_destroy (&extra);
449+
450+
future = future_collection_find_and_modify_with_opts (
451+
collection, tmp_bson ("{}"), opts, NULL, &error);
452+
request = mock_server_receives_command (
453+
server,
454+
"db",
455+
MONGOC_QUERY_NONE,
456+
"{'findAndModify': 'collection', 'writeConcern': {'w': 2}}");
457+
mock_server_replies_ok_and_destroys (request);
458+
ASSERT_OR_PRINT (future_get_bool (future), error);
459+
future_destroy (future);
460+
461+
/* opts overrides collection */
462+
mongoc_collection_set_write_concern (collection, w3);
463+
future = future_collection_find_and_modify_with_opts (
464+
collection, tmp_bson ("{}"), opts, NULL, &error);
465+
466+
/* still w: 2 */
467+
request = mock_server_receives_command (
468+
server,
469+
"db",
470+
MONGOC_QUERY_NONE,
471+
"{'findAndModify': 'collection', 'writeConcern': {'w': 2}}");
472+
mock_server_replies_ok_and_destroys (request);
473+
ASSERT_OR_PRINT (future_get_bool (future), error);
474+
future_destroy (future);
475+
476+
mongoc_find_and_modify_opts_destroy (opts);
477+
mongoc_collection_destroy (collection);
478+
mongoc_client_destroy (client);
479+
mock_server_destroy (server);
480+
mongoc_write_concern_destroy (w2);
481+
mongoc_write_concern_destroy (w3);
482+
}
483+
484+
419485
static void
420486
test_find_and_modify_collation (int wire)
421487
{
@@ -518,6 +584,9 @@ test_find_and_modify_install (TestSuite *suite)
518584
should_run_fam_wc);
519585
TestSuite_AddMockServerTest (
520586
suite, "/find_and_modify/opts", test_find_and_modify_opts);
587+
TestSuite_AddMockServerTest (suite,
588+
"/find_and_modify/opts/write_concern",
589+
test_find_and_modify_opts_write_concern);
521590
TestSuite_AddMockServerTest (suite,
522591
"/find_and_modify/collation/ok",
523592
test_find_and_modify_collation_ok);

0 commit comments

Comments
 (0)