Skip to content

Commit 1b9ce0d

Browse files
committed
CDRIVER-3552 allow hinting delete commands
1 parent 25a283d commit 1b9ce0d

File tree

56 files changed

+5777
-227
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

56 files changed

+5777
-227
lines changed

build/generate-opts.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -177,14 +177,18 @@ def __init__(self, items, **defaults):
177177
bypass_option,
178178
], validate='_mongoc_default_insert_vflags', ordered='true')),
179179

180-
('mongoc_delete_one_opts_t', Struct([
180+
('mongoc_delete_opts_t', Shared([
181181
('crud', {'type': 'mongoc_crud_opts_t'}),
182182
collation_option,
183+
hint_option,
184+
])),
185+
186+
('mongoc_delete_one_opts_t', Struct([
187+
('delete', {'type': 'mongoc_delete_opts_t'}),
183188
])),
184189

185190
('mongoc_delete_many_opts_t', Struct([
186-
('crud', {'type': 'mongoc_crud_opts_t'}),
187-
collation_option,
191+
('delete', {'type': 'mongoc_delete_opts_t'}),
188192
])),
189193

190194
('mongoc_update_one_opts_t', Struct([
@@ -248,6 +252,7 @@ def __init__(self, items, **defaults):
248252

249253
('mongoc_bulk_remove_opts_t', Shared([
250254
collation_option,
255+
hint_option,
251256
('limit', {'type': 'int32_t', 'hidden': True})
252257
])),
253258

src/libmongoc/doc/includes/bulk-remove-many-opts.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,4 @@
66
``opts`` may be NULL or a BSON document with additional command options:
77

88
* ``collation``: Configure textual comparisons. See :ref:`Setting Collation Order <setting_collation_order>`, and `the MongoDB Manual entry on Collation <https://docs.mongodb.com/manual/reference/collation/>`_. Collation requires MongoDB 3.2 or later, otherwise an error is returned.
9+
* ``hint``: A document or string that specifies the index to use to support the query predicate.

src/libmongoc/doc/includes/bulk-remove-one-opts.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,4 @@
66
``opts`` may be NULL or a BSON document with additional command options:
77

88
* ``collation``: Configure textual comparisons. See :ref:`Setting Collation Order <setting_collation_order>`, and `the MongoDB Manual entry on Collation <https://docs.mongodb.com/manual/reference/collation/>`_. Collation requires MongoDB 3.2 or later, otherwise an error is returned.
9+
* ``hint``: A document or string that specifies the index to use to support the query predicate.

src/libmongoc/doc/includes/delete-many-opts.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,4 @@
99
* ``sessionId``: First, construct a :symbol:`mongoc_client_session_t` with :symbol:`mongoc_client_start_session`. You can begin a transaction with :symbol:`mongoc_client_session_start_transaction`, optionally with a :symbol:`mongoc_transaction_opt_t` that overrides the options inherited from |opts-source|, and use :symbol:`mongoc_client_session_append` to add the session to ``opts``. See the example code for :symbol:`mongoc_client_session_t`.
1010
* ``validate``: Construct a bitwise-or of all desired :symbol:`bson_validate_flags_t <bson_validate_with_error>`. Set to ``false`` to skip client-side validation of the provided BSON documents.
1111
* ``collation``: Configure textual comparisons. See :ref:`Setting Collation Order <setting_collation_order>`, and `the MongoDB Manual entry on Collation <https://docs.mongodb.com/manual/reference/collation/>`_. Collation requires MongoDB 3.2 or later, otherwise an error is returned.
12+
* ``hint``: A document or string that specifies the index to use to support the query predicate.

src/libmongoc/doc/includes/delete-one-opts.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,4 @@
99
* ``sessionId``: First, construct a :symbol:`mongoc_client_session_t` with :symbol:`mongoc_client_start_session`. You can begin a transaction with :symbol:`mongoc_client_session_start_transaction`, optionally with a :symbol:`mongoc_transaction_opt_t` that overrides the options inherited from |opts-source|, and use :symbol:`mongoc_client_session_append` to add the session to ``opts``. See the example code for :symbol:`mongoc_client_session_t`.
1010
* ``validate``: Construct a bitwise-or of all desired :symbol:`bson_validate_flags_t <bson_validate_with_error>`. Set to ``false`` to skip client-side validation of the provided BSON documents.
1111
* ``collation``: Configure textual comparisons. See :ref:`Setting Collation Order <setting_collation_order>`, and `the MongoDB Manual entry on Collation <https://docs.mongodb.com/manual/reference/collation/>`_. Collation requires MongoDB 3.2 or later, otherwise an error is returned.
12+
* ``hint``: A document or string that specifies the index to use to support the query predicate.

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,7 @@ _mongoc_bulk_operation_remove_with_opts (
148148
bson_t opts;
149149
bool has_collation;
150150
bool ret = false;
151+
bool has_delete_hint;
151152

152153
ENTRY;
153154

@@ -174,11 +175,17 @@ _mongoc_bulk_operation_remove_with_opts (
174175
bson_append_document (&opts, "collation", 9, &remove_opts->collation);
175176
}
176177

178+
has_delete_hint = !!(remove_opts->hint.value_type);
179+
if (has_delete_hint) {
180+
bson_append_value (&opts, "hint", 4, &remove_opts->hint);
181+
}
182+
177183
if (bulk->commands.len) {
178184
last = &_mongoc_array_index (
179185
&bulk->commands, mongoc_write_command_t, bulk->commands.len - 1);
180186
if (last->type == MONGOC_WRITE_COMMAND_DELETE) {
181187
last->flags.has_collation |= has_collation;
188+
last->flags.has_delete_hint |= has_delete_hint;
182189
last->flags.has_multi_write |= (remove_opts->limit == 0);
183190
_mongoc_write_command_delete_append (last, selector, &opts);
184191
ret = true;
@@ -190,6 +197,7 @@ _mongoc_bulk_operation_remove_with_opts (
190197
&command, selector, NULL, &opts, bulk->flags, bulk->operation_id);
191198

192199
command.flags.has_collation = has_collation;
200+
command.flags.has_delete_hint = has_delete_hint;
193201
command.flags.has_multi_write = (remove_opts->limit == 0);
194202

195203
_mongoc_array_append_val (&bulk->commands, command);

src/libmongoc/src/mongoc/mongoc-client-private.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,8 @@ BSON_BEGIN_DECLS
5959
#define WIRE_VERSION_CMD_WRITE_CONCERN 5
6060
/* first version to support collation */
6161
#define WIRE_VERSION_COLLATION 5
62+
/* first version to support server-side errors for unsupported hint options */
63+
#define WIRE_VERSION_HINT_SERVER_SIDE_ERROR 5
6264
/* first version to support OP_MSG */
6365
#define WIRE_VERSION_OP_MSG 6
6466
/* first version to support array filters for "update" command */
@@ -75,6 +77,13 @@ BSON_BEGIN_DECLS
7577
#define WIRE_VERSION_4_2 8
7678
/* version corresponding to client side field level encryption support. */
7779
#define WIRE_VERSION_CSE 8
80+
/* first version to throw server-side errors for unsupported hint in
81+
* "findAndModify" command */
82+
#define WIRE_VERSION_FIND_AND_MODIFY_HINT_SERVER_SIDE_ERROR 8
83+
/* first version to support hint for "delete" command */
84+
#define WIRE_VERSION_DELETE_HINT 9
85+
/* first version to support hint for "findAndModify" command */
86+
#define WIRE_VERSION_FIND_AND_MODIFY_HINT 9
7887
/* version corresponding to server 4.4 release */
7988
#define WIRE_VERSION_4_4 9
8089
/* version corresponding to retryable writes error label */

src/libmongoc/src/mongoc/mongoc-collection.c

Lines changed: 58 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -2318,9 +2318,8 @@ static bool
23182318
_mongoc_delete_one_or_many (mongoc_collection_t *collection,
23192319
bool multi,
23202320
const bson_t *selector,
2321-
mongoc_crud_opts_t *crud,
2321+
mongoc_delete_opts_t *delete_opts,
23222322
const bson_t *cmd_opts,
2323-
const bson_t *collation,
23242323
bson_t *opts,
23252324
bson_t *reply,
23262325
bson_error_t *error)
@@ -2338,8 +2337,12 @@ _mongoc_delete_one_or_many (mongoc_collection_t *collection,
23382337
_mongoc_write_result_init (&result);
23392338
bson_append_int32 (opts, "limit", 5, multi ? 0 : 1);
23402339

2341-
if (!bson_empty (collation)) {
2342-
bson_append_document (opts, "collation", 9, collation);
2340+
if (!bson_empty (&delete_opts->collation)) {
2341+
bson_append_document (opts, "collation", 9, &delete_opts->collation);
2342+
}
2343+
2344+
if (delete_opts->hint.value_type) {
2345+
bson_append_value (opts, "hint", 4, &delete_opts->hint);
23432346
}
23442347

23452348
_mongoc_write_command_init_delete_idl (
@@ -2350,17 +2353,20 @@ _mongoc_delete_one_or_many (mongoc_collection_t *collection,
23502353
++collection->client->cluster.operation_id);
23512354

23522355
command.flags.has_multi_write = multi;
2353-
if (!bson_empty (collation)) {
2356+
if (!bson_empty (&delete_opts->collation)) {
23542357
command.flags.has_collation = true;
23552358
}
2359+
if (delete_opts->hint.value_type) {
2360+
command.flags.has_delete_hint = true;
2361+
}
23562362

23572363
_mongoc_collection_write_command_execute_idl (
2358-
&command, collection, crud, &result);
2364+
&command, collection, &delete_opts->crud, &result);
23592365

23602366
/* set field described in CRUD spec for the DeleteResult */
23612367
ret = MONGOC_WRITE_RESULT_COMPLETE (&result,
23622368
collection->client->error_api_version,
2363-
crud->writeConcern,
2369+
delete_opts->crud.writeConcern,
23642370
/* no error domain override */
23652371
(mongoc_error_domain_t) 0,
23662372
reply,
@@ -2399,9 +2405,8 @@ mongoc_collection_delete_one (mongoc_collection_t *collection,
23992405
ret = _mongoc_delete_one_or_many (collection,
24002406
false /* multi */,
24012407
selector,
2402-
&delete_one_opts.crud,
2408+
&delete_one_opts.delete,
24032409
&delete_one_opts.extra,
2404-
&delete_one_opts.collation,
24052410
&limit,
24062411
reply,
24072412
error);
@@ -2438,9 +2443,8 @@ mongoc_collection_delete_many (mongoc_collection_t *collection,
24382443
ret = _mongoc_delete_one_or_many (collection,
24392444
true /* multi */,
24402445
selector,
2441-
&delete_many_opts.crud,
2446+
&delete_many_opts.delete,
24422447
&delete_many_opts.extra,
2443-
&delete_many_opts.collation,
24442448
&limit,
24452449
reply,
24462450
error);
@@ -3031,6 +3035,7 @@ mongoc_collection_find_and_modify_with_opts (
30313035
mongoc_server_stream_t *server_stream = NULL;
30323036
mongoc_server_stream_t *retry_server_stream = NULL;
30333037
mongoc_find_and_modify_appended_opts_t appended_opts;
3038+
mongoc_write_concern_t *write_concern = NULL;
30343039

30353040
ENTRY;
30363041

@@ -3062,15 +3067,6 @@ mongoc_collection_find_and_modify_with_opts (
30623067
GOTO (done);
30633068
}
30643069

3065-
if (appended_opts.hint.value_type &&
3066-
server_stream->sd->max_wire_version < WIRE_VERSION_4_2) {
3067-
bson_set_error (error,
3068-
MONGOC_ERROR_COMMAND,
3069-
MONGOC_ERROR_PROTOCOL_BAD_WIRE_VERSION,
3070-
"selected server does not support hint on findAndModify");
3071-
GOTO (done);
3072-
}
3073-
30743070
name = mongoc_collection_get_name (collection);
30753071
BSON_APPEND_UTF8 (&command, "findAndModify", name);
30763072
BSON_APPEND_DOCUMENT (&command, "query", query);
@@ -3120,16 +3116,49 @@ mongoc_collection_find_and_modify_with_opts (
31203116
}
31213117

31223118
if (appended_opts.writeConcern) {
3123-
if (!mongoc_cmd_parts_set_write_concern (
3124-
&parts,
3125-
appended_opts.writeConcern,
3126-
server_stream->sd->max_wire_version,
3127-
error)) {
3119+
if (_mongoc_client_session_in_txn (parts.assembled.session)) {
3120+
bson_set_error (error,
3121+
MONGOC_ERROR_COMMAND,
3122+
MONGOC_ERROR_COMMAND_INVALID_ARG,
3123+
"Cannot set write concern after starting transaction");
31283124
GOTO (done);
31293125
}
3126+
3127+
write_concern = appended_opts.writeConcern;
3128+
}
3129+
3130+
if (!write_concern) {
3131+
if (server_stream->sd->max_wire_version >=
3132+
WIRE_VERSION_FAM_WRITE_CONCERN &&
3133+
(mongoc_write_concern_is_acknowledged (collection->write_concern) ||
3134+
!_mongoc_client_session_in_txn (parts.assembled.session))) {
3135+
if (!mongoc_write_concern_is_valid (collection->write_concern)) {
3136+
bson_set_error (error,
3137+
MONGOC_ERROR_COMMAND,
3138+
MONGOC_ERROR_COMMAND_INVALID_ARG,
3139+
"The write concern is invalid.");
3140+
GOTO (done);
3141+
}
3142+
3143+
write_concern = collection->write_concern;
3144+
}
31303145
}
31313146

31323147
if (appended_opts.hint.value_type) {
3148+
int max_wire_version =
3149+
mongoc_write_concern_is_acknowledged (write_concern)
3150+
? WIRE_VERSION_FIND_AND_MODIFY_HINT_SERVER_SIDE_ERROR
3151+
: WIRE_VERSION_FIND_AND_MODIFY_HINT;
3152+
3153+
if (server_stream->sd->max_wire_version < max_wire_version) {
3154+
bson_set_error (
3155+
error,
3156+
MONGOC_ERROR_COMMAND,
3157+
MONGOC_ERROR_PROTOCOL_BAD_WIRE_VERSION,
3158+
"selected server does not support hint on findAndModify");
3159+
GOTO (done);
3160+
}
3161+
31333162
bson_append_value (&parts.extra, "hint", 4, &appended_opts.hint);
31343163
}
31353164

@@ -3143,38 +3172,13 @@ mongoc_collection_find_and_modify_with_opts (
31433172
}
31443173
}
31453174

3146-
if (_mongoc_client_session_in_txn (parts.assembled.session) &&
3147-
appended_opts.writeConcern) {
3148-
bson_set_error (error,
3149-
MONGOC_ERROR_COMMAND,
3150-
MONGOC_ERROR_COMMAND_INVALID_ARG,
3151-
"Cannot set write concern after starting transaction");
3175+
/* An empty write concern amounts to a no-op, so there's no need to guard
3176+
* against it. */
3177+
if (!mongoc_cmd_parts_set_write_concern (
3178+
&parts, write_concern, server_stream->sd->max_wire_version, error)) {
31523179
GOTO (done);
31533180
}
31543181

3155-
if (!appended_opts.writeConcern) {
3156-
if (server_stream->sd->max_wire_version >=
3157-
WIRE_VERSION_FAM_WRITE_CONCERN) {
3158-
if (!mongoc_write_concern_is_valid (collection->write_concern)) {
3159-
bson_set_error (error,
3160-
MONGOC_ERROR_COMMAND,
3161-
MONGOC_ERROR_COMMAND_INVALID_ARG,
3162-
"The write concern is invalid.");
3163-
GOTO (done);
3164-
}
3165-
3166-
if (mongoc_write_concern_is_acknowledged (collection->write_concern)) {
3167-
if (!mongoc_cmd_parts_set_write_concern (
3168-
&parts,
3169-
collection->write_concern,
3170-
server_stream->sd->max_wire_version,
3171-
error)) {
3172-
GOTO (done);
3173-
}
3174-
}
3175-
}
3176-
}
3177-
31783182
parts.assembled.operation_id = ++cluster->operation_id;
31793183
if (!mongoc_cmd_parts_assemble (&parts, server_stream, error)) {
31803184
GOTO (done);

src/libmongoc/src/mongoc/mongoc-opts-private.h

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,15 +46,19 @@ typedef struct _mongoc_insert_many_opts_t {
4646
bson_t extra;
4747
} mongoc_insert_many_opts_t;
4848

49-
typedef struct _mongoc_delete_one_opts_t {
49+
typedef struct _mongoc_delete_opts_t {
5050
mongoc_crud_opts_t crud;
5151
bson_t collation;
52+
bson_value_t hint;
53+
} mongoc_delete_opts_t;
54+
55+
typedef struct _mongoc_delete_one_opts_t {
56+
mongoc_delete_opts_t delete;
5257
bson_t extra;
5358
} mongoc_delete_one_opts_t;
5459

5560
typedef struct _mongoc_delete_many_opts_t {
56-
mongoc_crud_opts_t crud;
57-
bson_t collation;
61+
mongoc_delete_opts_t delete;
5862
bson_t extra;
5963
} mongoc_delete_many_opts_t;
6064

@@ -115,6 +119,7 @@ typedef struct _mongoc_bulk_replace_one_opts_t {
115119

116120
typedef struct _mongoc_bulk_remove_opts_t {
117121
bson_t collation;
122+
bson_value_t hint;
118123
int32_t limit;
119124
} mongoc_bulk_remove_opts_t;
120125

0 commit comments

Comments
 (0)