Skip to content

Commit ab59ef0

Browse files
authored
CDRIVER-655 return error on repeated calls to mongoc_bulk_operation_execute (#1937)
1 parent ec1dac5 commit ab59ef0

File tree

4 files changed

+79
-33
lines changed

4 files changed

+79
-33
lines changed

NEWS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ Unreleased (2.0.0)
2626
* `authMechanismProperties` is now validated and returns a client error for invalid or unsupported fields when the authentication mechanism is specified for:
2727
* GSSAPI: supported fields are SERVICE_NAME, CANONICALIZE_HOST_NAME, SERVICE_REALM, and SERVICE_HOST.
2828
* MONGODB-AWS: supported fields are AWS_SESSION_TOKEN.
29+
* Calling `mongoc_bulk_operation_execute` on the same `mongoc_bulk_operation_t` repeatedly is an error. Previously this was only discouraged in documentation.
2930

3031
## Removals
3132

src/libmongoc/doc/mongoc_bulk_operation_execute.rst

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,9 @@ Synopsis
1515
1616
This function executes all operations queued into the bulk operation. Unless ``ordered: false`` was specified in the ``opts`` passed to :symbol:`mongoc_collection_create_bulk_operation_with_opts()`, then forward progress will be stopped upon the first error.
1717

18-
It is only valid to call :symbol:`mongoc_bulk_operation_execute()` once. The ``mongoc_bulk_operation_t`` must be destroyed afterwards.
18+
It is only valid to call :symbol:`mongoc_bulk_operation_execute()` once on the same :symbol:`mongoc_bulk_operation_t`. Calling repeatedly results in error. Call :symbol:`mongoc_bulk_operation_destroy` to destroy ``bulk`` afterwards.
19+
20+
.. versionchanged:: 2.0.0 Calling :symbol:`mongoc_bulk_operation_execute()` repeatedly results in an error.
1921

2022
.. warning::
2123

src/libmongoc/src/mongoc/mongoc-bulk-operation.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -740,8 +740,8 @@ mongoc_bulk_operation_execute (mongoc_bulk_operation_t *bulk, /* IN */
740740
cluster = &bulk->client->cluster;
741741

742742
if (bulk->executed) {
743-
_mongoc_write_result_destroy (&bulk->result);
744-
_mongoc_write_result_init (&bulk->result);
743+
_mongoc_set_error (error, MONGOC_ERROR_COMMAND, MONGOC_ERROR_COMMAND_INVALID_ARG, "bulk write already executed");
744+
GOTO (err);
745745
}
746746

747747
bulk->executed = true;

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

Lines changed: 73 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -3753,51 +3753,76 @@ test_bulk_max_batch_size (void)
37533753
static void
37543754
test_bulk_new (void)
37553755
{
3756-
mongoc_bulk_operation_t *bulk;
37573756
mongoc_collection_t *collection;
37583757
mongoc_client_t *client;
37593758
bson_error_t error;
37603759
bson_t empty = BSON_INITIALIZER;
37613760
uint32_t r;
37623761

37633762
client = test_framework_new_default_client ();
3764-
BSON_ASSERT (client);
3763+
ASSERT (client);
37653764

37663765
collection = get_test_collection (client, "bulk_new");
3767-
BSON_ASSERT (collection);
3766+
ASSERT (collection);
37683767

3769-
bulk = mongoc_bulk_operation_new (true);
3770-
mongoc_bulk_operation_destroy (bulk);
3771-
3772-
bulk = mongoc_bulk_operation_new (true);
3773-
3774-
r = mongoc_bulk_operation_execute (bulk, NULL, &error);
3775-
BSON_ASSERT (!r);
3776-
ASSERT_CMPINT (error.domain, ==, MONGOC_ERROR_COMMAND);
3777-
ASSERT_CMPINT (error.code, ==, MONGOC_ERROR_COMMAND_INVALID_ARG);
3768+
// Can create and destroy:
3769+
{
3770+
mongoc_bulk_operation_t *bulk = mongoc_bulk_operation_new (true);
3771+
mongoc_bulk_operation_destroy (bulk);
3772+
}
37783773

3779-
mongoc_bulk_operation_set_database (bulk, "test");
3780-
r = mongoc_bulk_operation_execute (bulk, NULL, &error);
3781-
BSON_ASSERT (!r);
3782-
ASSERT_CMPINT (error.domain, ==, MONGOC_ERROR_COMMAND);
3783-
ASSERT_CMPINT (error.code, ==, MONGOC_ERROR_COMMAND_INVALID_ARG);
3774+
// Execute without a client is an error:
3775+
{
3776+
mongoc_bulk_operation_t *bulk = mongoc_bulk_operation_new (true);
3777+
r = mongoc_bulk_operation_execute (bulk, NULL, &error);
3778+
ASSERT (!r);
3779+
ASSERT_ERROR_CONTAINS (error, MONGOC_ERROR_COMMAND, MONGOC_ERROR_COMMAND_INVALID_ARG, "requires a client");
3780+
mongoc_bulk_operation_destroy (bulk);
3781+
}
37843782

3785-
mongoc_bulk_operation_set_collection (bulk, "test");
3786-
r = mongoc_bulk_operation_execute (bulk, NULL, &error);
3787-
BSON_ASSERT (!r);
3788-
ASSERT_CMPINT (error.domain, ==, MONGOC_ERROR_COMMAND);
3789-
ASSERT_CMPINT (error.code, ==, MONGOC_ERROR_COMMAND_INVALID_ARG);
3783+
// Execute with a database and no client is an error:
3784+
{
3785+
mongoc_bulk_operation_t *bulk = mongoc_bulk_operation_new (true);
3786+
mongoc_bulk_operation_set_database (bulk, "test");
3787+
r = mongoc_bulk_operation_execute (bulk, NULL, &error);
3788+
ASSERT (!r);
3789+
ASSERT_ERROR_CONTAINS (error, MONGOC_ERROR_COMMAND, MONGOC_ERROR_COMMAND_INVALID_ARG, "requires a client");
3790+
mongoc_bulk_operation_destroy (bulk);
3791+
}
37903792

3791-
mongoc_bulk_operation_set_client (bulk, client);
3792-
r = mongoc_bulk_operation_execute (bulk, NULL, &error);
3793-
BSON_ASSERT (!r);
3794-
ASSERT_CMPINT (error.domain, ==, MONGOC_ERROR_COMMAND);
3795-
ASSERT_CMPINT (error.code, ==, MONGOC_ERROR_COMMAND_INVALID_ARG);
3793+
// Execute with a database and collection and no client is an error:
3794+
{
3795+
mongoc_bulk_operation_t *bulk = mongoc_bulk_operation_new (true);
3796+
mongoc_bulk_operation_set_database (bulk, "test");
3797+
mongoc_bulk_operation_set_collection (bulk, "test");
3798+
r = mongoc_bulk_operation_execute (bulk, NULL, &error);
3799+
ASSERT (!r);
3800+
ASSERT_ERROR_CONTAINS (error, MONGOC_ERROR_COMMAND, MONGOC_ERROR_COMMAND_INVALID_ARG, "requires a client");
3801+
mongoc_bulk_operation_destroy (bulk);
3802+
}
37963803

3797-
mongoc_bulk_operation_insert (bulk, &empty);
3798-
ASSERT_OR_PRINT (mongoc_bulk_operation_execute (bulk, NULL, &error), error);
3804+
// Execute with no operations is an error:
3805+
{
3806+
mongoc_bulk_operation_t *bulk = mongoc_bulk_operation_new (true);
3807+
mongoc_bulk_operation_set_database (bulk, "test");
3808+
mongoc_bulk_operation_set_collection (bulk, "test");
3809+
mongoc_bulk_operation_set_client (bulk, client);
3810+
r = mongoc_bulk_operation_execute (bulk, NULL, &error);
3811+
ASSERT (!r);
3812+
ASSERT_ERROR_CONTAINS (error, MONGOC_ERROR_COMMAND, MONGOC_ERROR_COMMAND_INVALID_ARG, "empty bulk write");
3813+
mongoc_bulk_operation_destroy (bulk);
3814+
}
37993815

3800-
mongoc_bulk_operation_destroy (bulk);
3816+
// Execute with operations is OK:
3817+
{
3818+
mongoc_bulk_operation_t *bulk = mongoc_bulk_operation_new (true);
3819+
mongoc_bulk_operation_set_database (bulk, "test");
3820+
mongoc_bulk_operation_set_collection (bulk, "test");
3821+
mongoc_bulk_operation_set_client (bulk, client);
3822+
mongoc_bulk_operation_insert (bulk, &empty);
3823+
ASSERT_OR_PRINT (mongoc_bulk_operation_execute (bulk, NULL, &error), error);
3824+
mongoc_bulk_operation_destroy (bulk);
3825+
}
38013826

38023827
mongoc_collection_drop (collection, NULL);
38033828

@@ -4766,6 +4791,23 @@ test_bulk_write_set_client_updates_operation_id_when_client_changes (void)
47664791
mock_server_destroy (mock_server);
47674792
}
47684793

4794+
static void
4795+
test_multiple_execution (void)
4796+
{
4797+
mongoc_client_t *client = test_framework_new_default_client ();
4798+
mongoc_collection_t *coll = get_test_collection (client, "test_multiple_execution");
4799+
bson_error_t error;
4800+
mongoc_bulk_operation_t *bulk = mongoc_collection_create_bulk_operation (coll, true, NULL);
4801+
mongoc_bulk_operation_insert (bulk, tmp_bson ("{}"));
4802+
ASSERT_OR_PRINT (mongoc_bulk_operation_execute (bulk, NULL, &error), error);
4803+
ASSERT (!mongoc_bulk_operation_execute (bulk, NULL, &error));
4804+
ASSERT_ERROR_CONTAINS (error, MONGOC_ERROR_COMMAND, MONGOC_ERROR_COMMAND_INVALID_ARG, "bulk write already executed");
4805+
mongoc_bulk_operation_destroy (bulk);
4806+
mongoc_collection_destroy (coll);
4807+
mongoc_client_destroy (client);
4808+
}
4809+
4810+
47694811
void
47704812
test_bulk_install (TestSuite *suite)
47714813
{
@@ -4944,4 +4986,5 @@ test_bulk_install (TestSuite *suite)
49444986
TestSuite_AddMockServerTest (suite,
49454987
"/BulkOperation/set_client_updates_operation_id_when_client_changes",
49464988
test_bulk_write_set_client_updates_operation_id_when_client_changes);
4989+
TestSuite_AddLive (suite, "/BulkOperation/multiple_execution", test_multiple_execution);
49474990
}

0 commit comments

Comments
 (0)