@@ -139,7 +139,12 @@ mongoc_bulkwriteopts_destroy (mongoc_bulkwriteopts_t *self)
139139typedef enum { MODEL_OP_INSERT , MODEL_OP_UPDATE , MODEL_OP_DELETE } model_op_t ;
140140typedef struct {
141141 model_op_t op ;
142- bson_iter_t id_iter ;
142+ // `id_loc` locates the "_id" field of an insert document.
143+ struct {
144+ size_t op_start ; // Offset in `mongoc_bulkwrite_t::ops` to the BSON for the insert op: { "document": ... }
145+ size_t op_len ; // Length of insert op.
146+ uint32_t id_offset ; // Offset in the insert op to the "_id" field.
147+ } id_loc ;
143148 char * ns ;
144149} modeldata_t ;
145150
@@ -277,19 +282,14 @@ mongoc_bulkwrite_append_insertone (mongoc_bulkwrite_t *self,
277282 persisted_id_offset += existing_id_offset ;
278283 }
279284
280- BSON_ASSERT (_mongoc_buffer_append (& self -> ops , bson_get_data (& op ), op .len ));
281-
282- // Store an iterator to the document's `_id` in the persisted payload:
283- bson_iter_t persisted_id_iter ;
284- {
285- BSON_ASSERT (mcommon_in_range_size_t_unsigned (op .len ));
286- size_t start = self -> ops .len - (size_t ) op .len ;
287- BSON_ASSERT (bson_iter_init_from_data_at_offset (
288- & persisted_id_iter , self -> ops .data + start , (size_t ) op .len , persisted_id_offset , strlen ("_id" )));
289- }
285+ size_t op_start = self -> ops .len ; // Save location of `op` to retrieve `_id` later.
286+ BSON_ASSERT (mcommon_in_range_size_t_unsigned (op .len ));
287+ BSON_ASSERT (_mongoc_buffer_append (& self -> ops , bson_get_data (& op ), (size_t ) op .len ));
290288
291289 self -> n_ops ++ ;
292- modeldata_t md = {.op = MODEL_OP_INSERT , .id_iter = persisted_id_iter , .ns = bson_strdup (ns )};
290+ modeldata_t md = {.op = MODEL_OP_INSERT ,
291+ .id_loc = {.op_start = op_start , .op_len = (size_t ) op .len , .id_offset = persisted_id_offset },
292+ .ns = bson_strdup (ns )};
293293 _mongoc_array_append_val (& self -> arrayof_modeldata , md );
294294 bson_destroy (& op );
295295 return true;
@@ -1340,7 +1340,8 @@ static bool
13401340_bulkwritereturn_apply_result (mongoc_bulkwritereturn_t * self ,
13411341 const bson_t * result ,
13421342 size_t ops_doc_offset ,
1343- const mongoc_array_t * arrayof_modeldata )
1343+ const mongoc_array_t * arrayof_modeldata ,
1344+ const mongoc_buffer_t * ops )
13441345{
13451346 BSON_ASSERT_PARAM (self );
13461347 BSON_ASSERT_PARAM (result );
@@ -1458,7 +1459,10 @@ _bulkwritereturn_apply_result (mongoc_bulkwritereturn_t *self,
14581459 break ;
14591460 }
14601461 case MODEL_OP_INSERT : {
1461- _bulkwriteresult_set_insertresult (self -> res , & md -> id_iter , models_idx );
1462+ bson_iter_t id_iter ;
1463+ BSON_ASSERT (bson_iter_init_from_data_at_offset (
1464+ & id_iter , ops -> data + md -> id_loc .op_start , md -> id_loc .op_len , md -> id_loc .id_offset , strlen ("_id" )));
1465+ _bulkwriteresult_set_insertresult (self -> res , & id_iter , models_idx );
14621466 break ;
14631467 }
14641468 default :
@@ -1705,9 +1709,9 @@ mongoc_bulkwrite_execute (mongoc_bulkwrite_t *self, const mongoc_bulkwriteopts_t
17051709 bool batch_ok = false;
17061710 bson_t cmd_reply = BSON_INITIALIZER ;
17071711 mongoc_cursor_t * reply_cursor = NULL ;
1708- // `ops_byte_len` is the number of documents from `ops` to send in this batch.
1712+ // `ops_byte_len` is the number of bytes from `ops` to send in this batch.
17091713 size_t ops_byte_len = 0 ;
1710- // `ops_doc_len` is the number of bytes from `ops` to send in this batch.
1714+ // `ops_doc_len` is the number of documents from `ops` to send in this batch.
17111715 size_t ops_doc_len = 0 ;
17121716
17131717 if (ops_byte_offset == self -> ops .len ) {
@@ -1903,7 +1907,8 @@ mongoc_bulkwrite_execute (mongoc_bulkwrite_t *self, const mongoc_bulkwriteopts_t
19031907 // Iterate over cursor results.
19041908 const bson_t * result ;
19051909 while (mongoc_cursor_next (reply_cursor , & result )) {
1906- if (!_bulkwritereturn_apply_result (& ret , result , ops_doc_offset , & self -> arrayof_modeldata )) {
1910+ if (!_bulkwritereturn_apply_result (
1911+ & ret , result , ops_doc_offset , & self -> arrayof_modeldata , & self -> ops )) {
19071912 goto batch_fail ;
19081913 }
19091914 }
0 commit comments