@@ -61,6 +61,35 @@ static void php_phongo_bulkwritecommand_extract_id(bson_t* doc, zval** return_va
61
61
zval_ptr_dtor (& state .zchild );
62
62
}
63
63
64
+ // TODO: Make this a common utility function to share with BulkWrite.c
65
+ /* Returns whether the BSON array's keys are a sequence of integer strings
66
+ * starting with "0". */
67
+ static inline bool phongo_bulkwrite_bson_array_has_valid_keys (bson_t * array )
68
+ {
69
+ bson_iter_t iter ;
70
+
71
+ if (bson_empty (array )) {
72
+ return true;
73
+ }
74
+
75
+ if (bson_iter_init (& iter , array )) {
76
+ char key [12 ];
77
+ int count = 0 ;
78
+
79
+ while (bson_iter_next (& iter )) {
80
+ bson_snprintf (key , sizeof (key ), "%d" , count );
81
+
82
+ if (0 != strcmp (key , bson_iter_key (& iter ))) {
83
+ return false;
84
+ }
85
+
86
+ count ++ ;
87
+ }
88
+ }
89
+
90
+ return true;
91
+ }
92
+
64
93
/* Constructs a new BulkWrite */
65
94
static PHP_METHOD (MongoDB_Driver_BulkWriteCommand , __construct )
66
95
{
@@ -176,6 +205,28 @@ static bool phongo_bwc_parse_document(zval* zdocument, bson_t* bdocument, const
176
205
return true;
177
206
}
178
207
208
+ static bool phongo_bwc_parse_array (zval * zarray , bson_t * barray , const char * key )
209
+ {
210
+ if (Z_TYPE_P (zarray ) != IS_OBJECT && Z_TYPE_P (zarray ) != IS_ARRAY ) {
211
+ phongo_throw_exception (PHONGO_ERROR_INVALID_ARGUMENT , "Expected \"%s\" option to be array or object, %s given" , key , zend_get_type_by_const (Z_TYPE_P (zarray )));
212
+ return false;
213
+ }
214
+
215
+ // Explicitly allow MongoDB\BSON\PackedArray for array values
216
+ php_phongo_zval_to_bson (zarray , PHONGO_BSON_ALLOW_ROOT_ARRAY , barray , NULL );
217
+
218
+ if (EG (exception )) {
219
+ return false;
220
+ }
221
+
222
+ if (!phongo_bulkwrite_bson_array_has_valid_keys (barray )) {
223
+ phongo_throw_exception (PHONGO_ERROR_INVALID_ARGUMENT , "Expected \"%s\" option to yield array but got non-sequential keys" , key );
224
+ return false;
225
+ }
226
+
227
+ return true;
228
+ }
229
+
179
230
static PHP_METHOD (MongoDB_Driver_BulkWriteCommand , deleteMany )
180
231
{
181
232
php_phongo_bulkwritecommand_t * intern ;
@@ -378,32 +429,284 @@ static PHP_METHOD(MongoDB_Driver_BulkWriteCommand, insertOne)
378
429
379
430
static PHP_METHOD (MongoDB_Driver_BulkWriteCommand , replaceOne )
380
431
{
381
- php_phongo_bulkwritecommand_t * intern ;
432
+ php_phongo_bulkwritecommand_t * intern ;
433
+ char * ns ;
434
+ size_t ns_len ;
435
+ zval * zfilter ;
436
+ zval * zupdate ;
437
+ zval * zoptions = NULL ;
438
+ bson_t bfilter = BSON_INITIALIZER ;
439
+ bson_t bupdate = BSON_INITIALIZER ;
440
+ mongoc_bulkwrite_replaceoneopts_t * opts = NULL ;
441
+ bson_error_t error = { 0 };
382
442
383
443
intern = Z_BULKWRITECOMMAND_OBJ_P (getThis ());
384
444
385
- // TODO: implementation
386
- PHONGO_PARSE_PARAMETERS_NONE ();
445
+ PHONGO_PARSE_PARAMETERS_START (3 , 4 )
446
+ Z_PARAM_STRING (ns , ns_len )
447
+ Z_PARAM_ARRAY_OR_OBJECT (zfilter )
448
+ Z_PARAM_ARRAY_OR_OBJECT (zupdate )
449
+ Z_PARAM_OPTIONAL
450
+ Z_PARAM_ARRAY_OR_NULL (zoptions )
451
+ PHONGO_PARSE_PARAMETERS_END ();
452
+
453
+ if (strlen (ns ) != ns_len ) {
454
+ phongo_throw_exception (PHONGO_ERROR_INVALID_ARGUMENT , "Namespace string should not contain null bytes" );
455
+ return ;
456
+ }
457
+
458
+ php_phongo_zval_to_bson (zfilter , PHONGO_BSON_NONE , & bfilter , NULL );
459
+
460
+ if (EG (exception )) {
461
+ goto cleanup ;
462
+ }
463
+
464
+ // Explicitly allow MongoDB\BSON\PackedArray for update pipelines
465
+ php_phongo_zval_to_bson (zupdate , PHONGO_BSON_ALLOW_ROOT_ARRAY , & bupdate , NULL );
466
+
467
+ if (EG (exception )) {
468
+ goto cleanup ;
469
+ }
470
+
471
+ if (zoptions ) {
472
+ opts = mongoc_bulkwrite_replaceoneopts_new ();
473
+
474
+ if (php_array_existsc (zoptions , "collation" )) {
475
+ bson_t bcollation = BSON_INITIALIZER ;
476
+
477
+ if (!phongo_bwc_parse_document (php_array_fetchc_deref (zoptions , "collation" ), & bcollation , "collation" )) {
478
+ bson_destroy (& bcollation );
479
+ goto cleanup ;
480
+ }
481
+
482
+ mongoc_bulkwrite_replaceoneopts_set_collation (opts , & bcollation );
483
+ bson_destroy (& bcollation );
484
+ }
485
+
486
+ if (php_array_existsc (zoptions , "hint" )) {
487
+ bson_value_t bhint = { 0 };
488
+
489
+ if (!phongo_bwc_parse_hint (php_array_fetchc_deref (zoptions , "hint" ), & bhint )) {
490
+ bson_value_destroy (& bhint );
491
+ goto cleanup ;
492
+ }
493
+
494
+ mongoc_bulkwrite_replaceoneopts_set_hint (opts , & bhint );
495
+ bson_value_destroy (& bhint );
496
+ }
497
+
498
+ if (php_array_existsc (zoptions , "upsert" )) {
499
+ mongoc_bulkwrite_replaceoneopts_set_upsert (opts , php_array_fetchc_bool (zoptions , "upsert" ));
500
+ }
501
+ }
502
+
503
+ if (!mongoc_bulkwrite_append_replaceone (intern -> bw , ns , & bfilter , & bupdate , opts , & error )) {
504
+ phongo_throw_exception_from_bson_error_t (& error );
505
+ goto cleanup ;
506
+ }
507
+
508
+ intern -> num_ops ++ ;
509
+
510
+ cleanup :
511
+ bson_destroy (& bfilter );
512
+ bson_destroy (& bupdate );
513
+ mongoc_bulkwrite_replaceoneopts_destroy (opts );
387
514
}
388
515
389
516
static PHP_METHOD (MongoDB_Driver_BulkWriteCommand , updateMany )
390
517
{
391
- php_phongo_bulkwritecommand_t * intern ;
518
+ php_phongo_bulkwritecommand_t * intern ;
519
+ char * ns ;
520
+ size_t ns_len ;
521
+ zval * zfilter ;
522
+ zval * zupdate ;
523
+ zval * zoptions = NULL ;
524
+ bson_t bfilter = BSON_INITIALIZER ;
525
+ bson_t bupdate = BSON_INITIALIZER ;
526
+ mongoc_bulkwrite_updatemanyopts_t * opts = NULL ;
527
+ bson_error_t error = { 0 };
392
528
393
529
intern = Z_BULKWRITECOMMAND_OBJ_P (getThis ());
394
530
395
- // TODO: implementation
396
- PHONGO_PARSE_PARAMETERS_NONE ();
531
+ PHONGO_PARSE_PARAMETERS_START (3 , 4 )
532
+ Z_PARAM_STRING (ns , ns_len )
533
+ Z_PARAM_ARRAY_OR_OBJECT (zfilter )
534
+ Z_PARAM_ARRAY_OR_OBJECT (zupdate )
535
+ Z_PARAM_OPTIONAL
536
+ Z_PARAM_ARRAY_OR_NULL (zoptions )
537
+ PHONGO_PARSE_PARAMETERS_END ();
538
+
539
+ if (strlen (ns ) != ns_len ) {
540
+ phongo_throw_exception (PHONGO_ERROR_INVALID_ARGUMENT , "Namespace string should not contain null bytes" );
541
+ return ;
542
+ }
543
+
544
+ php_phongo_zval_to_bson (zfilter , PHONGO_BSON_NONE , & bfilter , NULL );
545
+
546
+ if (EG (exception )) {
547
+ goto cleanup ;
548
+ }
549
+
550
+ // Explicitly allow MongoDB\BSON\PackedArray for update pipelines
551
+ php_phongo_zval_to_bson (zupdate , PHONGO_BSON_ALLOW_ROOT_ARRAY , & bupdate , NULL );
552
+
553
+ if (EG (exception )) {
554
+ goto cleanup ;
555
+ }
556
+
557
+ if (zoptions ) {
558
+ opts = mongoc_bulkwrite_updatemanyopts_new ();
559
+
560
+ if (php_array_existsc (zoptions , "arrayFilters" )) {
561
+ bson_t barrayfilters = BSON_INITIALIZER ;
562
+
563
+ if (!phongo_bwc_parse_array (php_array_fetchc_deref (zoptions , "arrayFilters" ), & barrayfilters , "arrayFilters" )) {
564
+ bson_destroy (& barrayfilters );
565
+ goto cleanup ;
566
+ }
567
+
568
+ mongoc_bulkwrite_updatemanyopts_set_arrayfilters (opts , & barrayfilters );
569
+ bson_destroy (& barrayfilters );
570
+ }
571
+
572
+ if (php_array_existsc (zoptions , "collation" )) {
573
+ bson_t bcollation = BSON_INITIALIZER ;
574
+
575
+ if (!phongo_bwc_parse_document (php_array_fetchc_deref (zoptions , "collation" ), & bcollation , "collation" )) {
576
+ bson_destroy (& bcollation );
577
+ goto cleanup ;
578
+ }
579
+
580
+ mongoc_bulkwrite_updatemanyopts_set_collation (opts , & bcollation );
581
+ bson_destroy (& bcollation );
582
+ }
583
+
584
+ if (php_array_existsc (zoptions , "hint" )) {
585
+ bson_value_t bhint = { 0 };
586
+
587
+ if (!phongo_bwc_parse_hint (php_array_fetchc_deref (zoptions , "hint" ), & bhint )) {
588
+ bson_value_destroy (& bhint );
589
+ goto cleanup ;
590
+ }
591
+
592
+ mongoc_bulkwrite_updatemanyopts_set_hint (opts , & bhint );
593
+ bson_value_destroy (& bhint );
594
+ }
595
+
596
+ if (php_array_existsc (zoptions , "upsert" )) {
597
+ mongoc_bulkwrite_updatemanyopts_set_upsert (opts , php_array_fetchc_bool (zoptions , "upsert" ));
598
+ }
599
+ }
600
+
601
+ if (!mongoc_bulkwrite_append_updatemany (intern -> bw , ns , & bfilter , & bupdate , opts , & error )) {
602
+ phongo_throw_exception_from_bson_error_t (& error );
603
+ goto cleanup ;
604
+ }
605
+
606
+ intern -> num_ops ++ ;
607
+
608
+ cleanup :
609
+ bson_destroy (& bfilter );
610
+ bson_destroy (& bupdate );
611
+ mongoc_bulkwrite_updatemanyopts_destroy (opts );
397
612
}
398
613
399
614
static PHP_METHOD (MongoDB_Driver_BulkWriteCommand , updateOne )
400
615
{
401
- php_phongo_bulkwritecommand_t * intern ;
616
+ php_phongo_bulkwritecommand_t * intern ;
617
+ char * ns ;
618
+ size_t ns_len ;
619
+ zval * zfilter ;
620
+ zval * zupdate ;
621
+ zval * zoptions = NULL ;
622
+ bson_t bfilter = BSON_INITIALIZER ;
623
+ bson_t bupdate = BSON_INITIALIZER ;
624
+ mongoc_bulkwrite_updateoneopts_t * opts = NULL ;
625
+ bson_error_t error = { 0 };
402
626
403
627
intern = Z_BULKWRITECOMMAND_OBJ_P (getThis ());
404
628
405
- // TODO: implementation
406
- PHONGO_PARSE_PARAMETERS_NONE ();
629
+ PHONGO_PARSE_PARAMETERS_START (3 , 4 )
630
+ Z_PARAM_STRING (ns , ns_len )
631
+ Z_PARAM_ARRAY_OR_OBJECT (zfilter )
632
+ Z_PARAM_ARRAY_OR_OBJECT (zupdate )
633
+ Z_PARAM_OPTIONAL
634
+ Z_PARAM_ARRAY_OR_NULL (zoptions )
635
+ PHONGO_PARSE_PARAMETERS_END ();
636
+
637
+ if (strlen (ns ) != ns_len ) {
638
+ phongo_throw_exception (PHONGO_ERROR_INVALID_ARGUMENT , "Namespace string should not contain null bytes" );
639
+ return ;
640
+ }
641
+
642
+ php_phongo_zval_to_bson (zfilter , PHONGO_BSON_NONE , & bfilter , NULL );
643
+
644
+ if (EG (exception )) {
645
+ goto cleanup ;
646
+ }
647
+
648
+ // Explicitly allow MongoDB\BSON\PackedArray for update pipelines
649
+ php_phongo_zval_to_bson (zupdate , PHONGO_BSON_ALLOW_ROOT_ARRAY , & bupdate , NULL );
650
+
651
+ if (EG (exception )) {
652
+ goto cleanup ;
653
+ }
654
+
655
+ if (zoptions ) {
656
+ opts = mongoc_bulkwrite_updateoneopts_new ();
657
+
658
+ if (php_array_existsc (zoptions , "arrayFilters" )) {
659
+ bson_t barrayfilters = BSON_INITIALIZER ;
660
+
661
+ if (!phongo_bwc_parse_array (php_array_fetchc_deref (zoptions , "arrayFilters" ), & barrayfilters , "arrayFilters" )) {
662
+ bson_destroy (& barrayfilters );
663
+ goto cleanup ;
664
+ }
665
+
666
+ mongoc_bulkwrite_updateoneopts_set_arrayfilters (opts , & barrayfilters );
667
+ bson_destroy (& barrayfilters );
668
+ }
669
+
670
+ if (php_array_existsc (zoptions , "collation" )) {
671
+ bson_t bcollation = BSON_INITIALIZER ;
672
+
673
+ if (!phongo_bwc_parse_document (php_array_fetchc_deref (zoptions , "collation" ), & bcollation , "collation" )) {
674
+ bson_destroy (& bcollation );
675
+ goto cleanup ;
676
+ }
677
+
678
+ mongoc_bulkwrite_updateoneopts_set_collation (opts , & bcollation );
679
+ bson_destroy (& bcollation );
680
+ }
681
+
682
+ if (php_array_existsc (zoptions , "hint" )) {
683
+ bson_value_t bhint = { 0 };
684
+
685
+ if (!phongo_bwc_parse_hint (php_array_fetchc_deref (zoptions , "hint" ), & bhint )) {
686
+ bson_value_destroy (& bhint );
687
+ goto cleanup ;
688
+ }
689
+
690
+ mongoc_bulkwrite_updateoneopts_set_hint (opts , & bhint );
691
+ bson_value_destroy (& bhint );
692
+ }
693
+
694
+ if (php_array_existsc (zoptions , "upsert" )) {
695
+ mongoc_bulkwrite_updateoneopts_set_upsert (opts , php_array_fetchc_bool (zoptions , "upsert" ));
696
+ }
697
+ }
698
+
699
+ if (!mongoc_bulkwrite_append_updateone (intern -> bw , ns , & bfilter , & bupdate , opts , & error )) {
700
+ phongo_throw_exception_from_bson_error_t (& error );
701
+ goto cleanup ;
702
+ }
703
+
704
+ intern -> num_ops ++ ;
705
+
706
+ cleanup :
707
+ bson_destroy (& bfilter );
708
+ bson_destroy (& bupdate );
709
+ mongoc_bulkwrite_updateoneopts_destroy (opts );
407
710
}
408
711
409
712
/* MongoDB\Driver\BulkWriteCommand object handlers */
0 commit comments