@@ -304,11 +304,15 @@ mongoc_collection_aggregate (mongoc_collection_t *collection, /* IN */
304
304
const mongoc_read_prefs_t * read_prefs ) /* IN */
305
305
{
306
306
mongoc_server_description_t * selected_server = NULL ;
307
+ bool has_batch_size = false;
308
+ bool has_out_key = false;
309
+ bson_iter_t kiter ;
310
+ bson_iter_t ar ;
307
311
mongoc_cursor_t * cursor ;
312
+ int32_t batch_size = 0 ;
308
313
bson_iter_t iter ;
309
314
bson_t command ;
310
315
bson_t child ;
311
- int32_t batch_size = 0 ;
312
316
bool use_cursor ;
313
317
314
318
ENTRY ;
@@ -360,88 +364,65 @@ mongoc_collection_aggregate (mongoc_collection_t *collection, /* IN */
360
364
BSON_APPEND_ARRAY (& command , "pipeline" , pipeline );
361
365
}
362
366
367
+ if (bson_iter_init_find (& iter , pipeline , "pipeline" ) &&
368
+ BSON_ITER_HOLDS_ARRAY (& iter ) && bson_iter_recurse (& iter , & ar )) {
369
+ while (bson_iter_next (& ar )) {
370
+ if (BSON_ITER_HOLDS_DOCUMENT (& ar ) && bson_iter_recurse (& ar , & kiter )) {
371
+ has_out_key |= bson_iter_find (& kiter , "$out" );
372
+ }
373
+ }
374
+ }
375
+
363
376
/* for newer version, we include a cursor subdocument */
364
377
if (use_cursor ) {
365
378
bson_append_document_begin (& command , "cursor" , 6 , & child );
366
379
367
- if (opts && bson_iter_init (& iter , opts )) {
368
- while (bson_iter_next (& iter )) {
369
- if (BSON_ITER_IS_KEY (& iter , "batchSize" ) &&
370
- (BSON_ITER_HOLDS_INT32 (& iter ) ||
380
+ if (opts
381
+ && bson_iter_init_find (& iter , opts , "batchSize" )
382
+ && (BSON_ITER_HOLDS_INT32 (& iter ) ||
371
383
BSON_ITER_HOLDS_INT64 (& iter ) ||
372
384
BSON_ITER_HOLDS_DOUBLE (& iter ))) {
373
385
batch_size = (int32_t )bson_iter_as_int64 (& iter );
374
386
BSON_APPEND_INT32 (& child , "batchSize" , batch_size );
375
- }
376
- }
387
+ has_batch_size = true;
377
388
}
378
389
379
390
bson_append_document_end (& command , & child );
380
391
}
381
392
382
- if (opts && bson_iter_init (& iter , opts )) {
383
- while (bson_iter_next (& iter )) {
384
- if (!(BSON_ITER_IS_KEY (& iter , "batchSize" ) ||
385
- BSON_ITER_IS_KEY (& iter , "cursor" ) ||
386
- BSON_ITER_IS_KEY (& iter , "writeConcern" ))) {
387
- if (!bson_append_iter (& command , bson_iter_key (& iter ), -1 , & iter )) {
388
- bson_set_error (& cursor -> error ,
389
- MONGOC_ERROR_COMMAND ,
390
- MONGOC_ERROR_COMMAND_INVALID_ARG ,
391
- "Failed to append \"batchSize\" or \"cursor\" to create command." );
392
- GOTO (done );
393
- }
394
- }
395
- }
396
- }
397
-
398
- if (collection -> read_concern -> level != NULL ) {
399
- const bson_t * read_concern_bson ;
393
+ if (opts ) {
394
+ bool ok = false;
395
+ bson_t opts_dupe = BSON_INITIALIZER ;
400
396
401
- if (selected_server -> max_wire_version < WIRE_VERSION_READ_CONCERN ) {
402
- bson_set_error (& cursor -> error ,
403
- MONGOC_ERROR_COMMAND ,
404
- MONGOC_ERROR_PROTOCOL_BAD_WIRE_VERSION ,
405
- "The selected server does not support readConcern" );
406
- GOTO (done );
397
+ if (has_batch_size ) {
398
+ bson_copy_to_excluding_noinit (opts , & opts_dupe , "batchSize" , NULL );
399
+ bson_iter_init (& iter , & opts_dupe );
400
+ } else {
401
+ bson_iter_init (& iter , opts );
407
402
}
408
403
409
- read_concern_bson = _mongoc_read_concern_get_bson (collection -> read_concern );
410
- BSON_APPEND_DOCUMENT (& command , "readConcern" , read_concern_bson );
411
- }
404
+ ok = _mongoc_client_command_append_iterator_opts_to_command (& iter ,
405
+ selected_server -> max_wire_version ,
406
+ & command ,
407
+ & cursor -> error );
412
408
413
- if (opts && bson_iter_init_find (& iter , opts , "writeConcern" )
414
- && BSON_ITER_HOLDS_DOCUMENT (& iter )) {
415
- if (!_mongoc_write_concern_iter_is_valid (& iter )) {
416
- bson_set_error (& cursor -> error ,
417
- MONGOC_ERROR_COMMAND ,
418
- MONGOC_ERROR_COMMAND_INVALID_ARG ,
419
- "Invalid writeConcern" );
409
+ bson_destroy (& opts_dupe );
410
+
411
+ if (!ok ) {
420
412
GOTO (done );
421
413
}
414
+ }
422
415
423
- if ( selected_server -> max_wire_version >= WIRE_VERSION_CMD_WRITE_CONCERN ) {
424
- cursor -> write_concern = _mongoc_write_concern_new_from_iter ( & iter );
425
- }
416
+ /* Only inherit WriteConcern when for aggregate with $out */
417
+ if (! bson_has_field ( & command , "writeConcern" ) && has_out_key ) {
418
+ cursor -> write_concern = mongoc_write_concern_copy ( mongoc_collection_get_write_concern ( collection ));
426
419
}
427
- if (opts && bson_iter_init_find (& iter , opts , "collation" )
428
- && BSON_ITER_HOLDS_DOCUMENT (& iter )) {
429
- if (selected_server -> max_wire_version < WIRE_VERSION_COLLATION ) {
430
- bson_set_error (& cursor -> error ,
431
- MONGOC_ERROR_COMMAND ,
432
- MONGOC_ERROR_COMMAND_INVALID_ARG ,
433
- "The selected server does not support collation" );
434
- GOTO (done );
435
- }
436
- if (!bson_append_iter (& command , bson_iter_key (& iter ), -1 , & iter )) {
437
- bson_set_error (& cursor -> error ,
438
- MONGOC_ERROR_BSON ,
439
- MONGOC_ERROR_BSON_INVALID ,
440
- "Failed to append \"collation\" to create command." );
441
- GOTO (done );
442
- }
420
+
421
+ if (!bson_has_field (& command , "readConcern" )) {
422
+ cursor -> read_concern = mongoc_read_concern_copy (mongoc_collection_get_read_concern (collection ));
443
423
}
444
424
425
+
445
426
if (use_cursor ) {
446
427
_mongoc_cursor_cursorid_init (cursor , & command );
447
428
} else {
0 commit comments