@@ -822,6 +822,11 @@ struct _mongoc_bulkwriteresult_t {
822
822
int64_t matchedcount ;
823
823
int64_t modifiedcount ;
824
824
int64_t deletedcount ;
825
+ int64_t errorscount ; // sum of all `nErrors`.
826
+ struct {
827
+ bool isset ;
828
+ int64_t index ;
829
+ } first_error_index ;
825
830
uint32_t serverid ;
826
831
bson_t insertresults ;
827
832
bson_t updateresults ;
@@ -1253,6 +1258,12 @@ _bulkwritereturn_apply_reply (mongoc_bulkwritereturn_t *self, const bson_t *cmd_
1253
1258
}
1254
1259
self -> res -> upsertedcount += nUpserted ;
1255
1260
1261
+ int64_t nErrors ;
1262
+ if (!lookup_as_int64 (cmd_reply , "nErrors" , & nErrors , NULL , self -> exc )) {
1263
+ return false;
1264
+ }
1265
+ self -> res -> errorscount += nErrors ;
1266
+
1256
1267
bson_error_t error ;
1257
1268
bson_iter_t iter ;
1258
1269
if (bson_iter_init_find (& iter , cmd_reply , "writeConcernError" )) {
@@ -1332,6 +1343,10 @@ _bulkwritereturn_apply_result (mongoc_bulkwritereturn_t *self,
1332
1343
// `models_idx` is the index of the model that produced this result.
1333
1344
size_t models_idx = (size_t ) idx + ops_doc_offset ;
1334
1345
if (ok == 0 ) {
1346
+ if (!self -> res -> first_error_index .isset ) {
1347
+ self -> res -> first_error_index .isset = true;
1348
+ self -> res -> first_error_index .index = idx ;
1349
+ }
1335
1350
bson_iter_t result_iter ;
1336
1351
1337
1352
// Parse `code`.
@@ -1437,6 +1452,7 @@ mongoc_bulkwrite_execute (mongoc_bulkwrite_t *self, const mongoc_bulkwriteopts_t
1437
1452
BSON_ASSERT_PARAM (self );
1438
1453
BSON_OPTIONAL_PARAM (opts );
1439
1454
1455
+ bool has_successful_results = false;
1440
1456
mongoc_bulkwritereturn_t ret = {0 };
1441
1457
bson_error_t error = {0 };
1442
1458
mongoc_server_stream_t * ss = NULL ;
@@ -1447,6 +1463,8 @@ mongoc_bulkwrite_execute (mongoc_bulkwrite_t *self, const mongoc_bulkwriteopts_t
1447
1463
if (!opts ) {
1448
1464
opts = & defaults ;
1449
1465
}
1466
+ bool is_ordered =
1467
+ mongoc_optional_is_set (& opts -> ordered ) ? mongoc_optional_value (& opts -> ordered ) : true; // default.
1450
1468
bool is_acknowledged = false;
1451
1469
// Create empty result and exception to collect results/errors from batches.
1452
1470
ret .res = _bulkwriteresult_new ();
@@ -1506,8 +1524,7 @@ mongoc_bulkwrite_execute (mongoc_bulkwrite_t *self, const mongoc_bulkwriteopts_t
1506
1524
// errorsOnly is default true. Set to false if verboseResults requested.
1507
1525
BSON_ASSERT (BSON_APPEND_BOOL (& cmd , "errorsOnly" , !verboseresults ));
1508
1526
// ordered is default true.
1509
- BSON_ASSERT (BSON_APPEND_BOOL (
1510
- & cmd , "ordered" , (mongoc_optional_is_set (& opts -> ordered )) ? mongoc_optional_value (& opts -> ordered ) : true));
1527
+ BSON_ASSERT (BSON_APPEND_BOOL (& cmd , "ordered" , is_ordered ));
1511
1528
1512
1529
if (opts -> comment .value_type != BSON_TYPE_EOD ) {
1513
1530
BSON_ASSERT (BSON_APPEND_VALUE (& cmd , "comment" , & opts -> comment ));
@@ -1826,8 +1843,6 @@ mongoc_bulkwrite_execute (mongoc_bulkwrite_t *self, const mongoc_bulkwriteopts_t
1826
1843
if (!batch_ok ) {
1827
1844
goto fail ;
1828
1845
}
1829
- bool is_ordered =
1830
- mongoc_optional_is_set (& opts -> ordered ) ? mongoc_optional_value (& opts -> ordered ) : true; // default.
1831
1846
if (has_write_errors && is_ordered ) {
1832
1847
// Ordered writes must not continue to send batches once an error is
1833
1848
// occurred. An individual write error is not a top-level error.
@@ -1836,7 +1851,19 @@ mongoc_bulkwrite_execute (mongoc_bulkwrite_t *self, const mongoc_bulkwriteopts_t
1836
1851
}
1837
1852
1838
1853
fail :
1839
- if (!is_acknowledged ) {
1854
+ if (is_ordered ) {
1855
+ // Ordered writes stop on first error. If the error reported is for an index > 0, assume some writes suceeded.
1856
+ if (ret .res -> errorscount == 0 || (ret .res -> first_error_index .isset && ret .res -> first_error_index .index > 0 )) {
1857
+ has_successful_results = true;
1858
+ }
1859
+ } else {
1860
+ BSON_ASSERT (bson_in_range_size_t_signed (ret .res -> errorscount ));
1861
+ size_t errorscount_sz = (size_t ) ret .res -> errorscount ;
1862
+ if (errorscount_sz < self -> n_ops ) {
1863
+ has_successful_results = true;
1864
+ }
1865
+ }
1866
+ if (!is_acknowledged || !has_successful_results ) {
1840
1867
mongoc_bulkwriteresult_destroy (ret .res );
1841
1868
ret .res = NULL ;
1842
1869
}
0 commit comments