Skip to content

Commit 5203b21

Browse files
committed
CDRIVER-5816 allow constructing mongoc_bulkwrite_t without a client
1 parent 028b987 commit 5203b21

File tree

6 files changed

+129
-2
lines changed

6 files changed

+129
-2
lines changed
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
:man_page: mongoc_bulkwrite_new
2+
3+
mongoc_bulkwrite_new()
4+
======================
5+
6+
Synopsis
7+
--------
8+
9+
.. code-block:: c
10+
11+
mongoc_bulkwrite_t *
12+
mongoc_bulkwrite_new (void);
13+
14+
Description
15+
-----------
16+
17+
Returns a new :symbol:`mongoc_bulkwrite_t`. Free with :symbol:`mongoc_bulkwrite_destroy()`.
18+
19+
A client must be assigned with :symbol:`mongoc_bulkwrite_set_client()` prior to execution.
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
:man_page: mongoc_bulkwrite_set_client
2+
3+
mongoc_bulkwrite_set_client()
4+
=============================
5+
6+
Synopsis
7+
--------
8+
9+
.. code-block:: c
10+
11+
void
12+
mongoc_bulkwrite_set_client (mongoc_bulkwrite_t *self, mongoc_client_t *client);
13+
14+
Description
15+
-----------
16+
17+
Sets the client that will be used to execute the :symbol:`mongoc_bulkwrite_t`.

src/libmongoc/doc/mongoc_bulkwrite_t.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,8 @@ to execute the operation.
5050
mongoc_bulkwrite_deletemanyopts_t
5151
mongoc_bulkwrite_append_deletemany
5252
mongoc_bulkwritereturn_t
53+
mongoc_bulkwrite_new
54+
mongoc_bulkwrite_set_client
5355
mongoc_bulkwrite_set_session
5456
mongoc_bulkwrite_execute
5557
mongoc_bulkwrite_destroy

src/libmongoc/src/mongoc/mongoc-bulkwrite.c

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -169,11 +169,18 @@ mongoc_bulkwrite_t *
169169
mongoc_client_bulkwrite_new (mongoc_client_t *self)
170170
{
171171
BSON_ASSERT_PARAM (self);
172-
mongoc_bulkwrite_t *bw = bson_malloc0 (sizeof (mongoc_bulkwrite_t));
172+
mongoc_bulkwrite_t *bw = mongoc_bulkwrite_new ();
173173
bw->client = self;
174+
bw->operation_id = ++self->cluster.operation_id;
175+
return bw;
176+
}
177+
178+
mongoc_bulkwrite_t *
179+
mongoc_bulkwrite_new (void)
180+
{
181+
mongoc_bulkwrite_t *bw = bson_malloc0 (sizeof (mongoc_bulkwrite_t));
174182
_mongoc_buffer_init (&bw->ops, NULL, 0, NULL, NULL);
175183
_mongoc_array_init (&bw->arrayof_modeldata, sizeof (modeldata_t));
176-
bw->operation_id = ++self->cluster.operation_id;
177184
return bw;
178185
}
179186

@@ -1462,6 +1469,26 @@ _bulkwritereturn_apply_result (mongoc_bulkwritereturn_t *self,
14621469
return true;
14631470
}
14641471

1472+
void
1473+
mongoc_bulkwrite_set_client (mongoc_bulkwrite_t *self, mongoc_client_t *client)
1474+
{
1475+
BSON_ASSERT_PARAM (self);
1476+
BSON_ASSERT_PARAM (client);
1477+
1478+
if (self->session) {
1479+
BSON_ASSERT (self->session->client == client);
1480+
}
1481+
1482+
/* NOP if the client is not changing; otherwise, assign it and increment and
1483+
* fetch its operation_id. */
1484+
if (self->client == client) {
1485+
return;
1486+
}
1487+
1488+
self->client = client;
1489+
self->operation_id = ++client->cluster.operation_id;
1490+
}
1491+
14651492
void
14661493
mongoc_bulkwrite_set_session (mongoc_bulkwrite_t *self, mongoc_client_session_t *session)
14671494
{
@@ -1495,6 +1522,15 @@ mongoc_bulkwrite_execute (mongoc_bulkwrite_t *self, const mongoc_bulkwriteopts_t
14951522
ret.res = _bulkwriteresult_new ();
14961523
ret.exc = _bulkwriteexception_new ();
14971524

1525+
if (!self->client) {
1526+
bson_set_error (&error,
1527+
MONGOC_ERROR_COMMAND,
1528+
MONGOC_ERROR_COMMAND_INVALID_ARG,
1529+
"bulk write requires a client and one has not been set");
1530+
_bulkwriteexception_set_error (ret.exc, &error);
1531+
goto fail;
1532+
}
1533+
14981534
if (self->executed) {
14991535
bson_set_error (&error, MONGOC_ERROR_COMMAND, MONGOC_ERROR_COMMAND_INVALID_ARG, "bulk write already executed");
15001536
_bulkwriteexception_set_error (ret.exc, &error);

src/libmongoc/src/mongoc/mongoc-bulkwrite.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,7 @@ mongoc_bulkwriteexception_destroy (mongoc_bulkwriteexception_t *self);
127127
typedef struct _mongoc_bulkwrite_t mongoc_bulkwrite_t;
128128
MONGOC_EXPORT (mongoc_bulkwrite_t *)
129129
mongoc_client_bulkwrite_new (mongoc_client_t *self);
130+
130131
typedef struct _mongoc_bulkwrite_insertoneopts_t mongoc_bulkwrite_insertoneopts_t;
131132
MONGOC_EXPORT (mongoc_bulkwrite_insertoneopts_t *)
132133
mongoc_bulkwrite_insertoneopts_new (void);
@@ -243,6 +244,13 @@ typedef struct {
243244
mongoc_bulkwriteexception_t *exc; // NULL if no error.
244245
} mongoc_bulkwritereturn_t;
245246

247+
// `mongoc_bulkwrite_new` and `mongoc_bulkwrite_set_client` may be used by
248+
// language bindings that want to assemble a `mongoc_bulkwrite_t` and defer
249+
// `mongoc_client_t` assignment to execution time.
250+
MONGOC_EXPORT (mongoc_bulkwrite_t *)
251+
mongoc_bulkwrite_new (void);
252+
MONGOC_EXPORT (void)
253+
mongoc_bulkwrite_set_client (mongoc_bulkwrite_t *self, mongoc_client_t *client);
246254
// `mongoc_bulkwrite_set_session` sets an optional explicit session.
247255
// `*session` may be modified when `mongoc_bulkwrite_execute` is called.
248256
MONGOC_EXPORT (void)

src/libmongoc/tests/test-mongoc-bulkwrite.c

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -591,6 +591,43 @@ test_bulkwrite_many_namespaces (void *ctx)
591591
mongoc_client_destroy (client);
592592
}
593593

594+
static void
595+
test_bulkwrite_execute_requires_client (void *ctx)
596+
{
597+
BSON_UNUSED (ctx);
598+
bool ok;
599+
bson_error_t error;
600+
601+
mongoc_client_t *client = test_framework_new_default_client ();
602+
mongoc_bulkwrite_t *bw = mongoc_bulkwrite_new ();
603+
ok = mongoc_bulkwrite_append_insertone (bw, "db.coll", tmp_bson ("{}"), NULL, &error);
604+
ASSERT_OR_PRINT (ok, error);
605+
606+
// Attempt execution without assigning a client
607+
{
608+
mongoc_bulkwritereturn_t bwr = mongoc_bulkwrite_execute (bw, NULL);
609+
ASSERT (bwr.exc);
610+
ASSERT (mongoc_bulkwriteexception_error (bwr.exc, &error));
611+
ASSERT_ERROR_CONTAINS (error,
612+
MONGOC_ERROR_COMMAND,
613+
MONGOC_ERROR_COMMAND_INVALID_ARG,
614+
"bulk write requires a client and one has not been set");
615+
mongoc_bulkwriteexception_destroy (bwr.exc);
616+
mongoc_bulkwriteresult_destroy (bwr.res);
617+
}
618+
619+
// Assign a client and execute successfully
620+
{
621+
mongoc_bulkwrite_set_client (bw, client);
622+
mongoc_bulkwritereturn_t bwr = mongoc_bulkwrite_execute (bw, NULL);
623+
ASSERT_NO_BULKWRITEEXCEPTION (bwr);
624+
mongoc_bulkwriteresult_destroy (bwr.res);
625+
mongoc_bulkwriteexception_destroy (bwr.exc);
626+
}
627+
628+
mongoc_bulkwrite_destroy (bw);
629+
mongoc_client_destroy (client);
630+
}
594631

595632
void
596633
test_bulkwrite_install (TestSuite *suite)
@@ -677,4 +714,12 @@ test_bulkwrite_install (TestSuite *suite)
677714
test_framework_skip_if_max_wire_version_less_than_25, // require server 8.0
678715
test_framework_skip_if_mongos // Creating 100k collections is very slow (~5 minutes) on mongos.
679716
);
717+
718+
TestSuite_AddFull (suite,
719+
"/bulkwrite/execute_requires_client",
720+
test_bulkwrite_execute_requires_client,
721+
NULL /* dtor */,
722+
NULL /* ctx */,
723+
test_framework_skip_if_max_wire_version_less_than_25 // require server 8.0
724+
);
680725
}

0 commit comments

Comments
 (0)