@@ -61,6 +61,35 @@ static void php_phongo_bulkwritecommand_extract_id(bson_t* doc, zval** return_va
6161 zval_ptr_dtor (& state .zchild );
6262}
6363
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+ 6493/* Constructs a new BulkWrite */
6594static PHP_METHOD (MongoDB_Driver_BulkWriteCommand , __construct )
6695{
@@ -176,6 +205,28 @@ static bool phongo_bwc_parse_document(zval* zdocument, bson_t* bdocument, const
176205 return true;
177206}
178207
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+ 179230static PHP_METHOD (MongoDB_Driver_BulkWriteCommand , deleteMany )
180231{
181232 php_phongo_bulkwritecommand_t * intern ;
@@ -378,32 +429,284 @@ static PHP_METHOD(MongoDB_Driver_BulkWriteCommand, insertOne)
378429
379430static PHP_METHOD (MongoDB_Driver_BulkWriteCommand , replaceOne )
380431{
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 };
382442
383443 intern = Z_BULKWRITECOMMAND_OBJ_P (getThis ());
384444
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 );
387514}
388515
389516static PHP_METHOD (MongoDB_Driver_BulkWriteCommand , updateMany )
390517{
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 };
392528
393529 intern = Z_BULKWRITECOMMAND_OBJ_P (getThis ());
394530
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 );
397612}
398613
399614static PHP_METHOD (MongoDB_Driver_BulkWriteCommand , updateOne )
400615{
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 };
402626
403627 intern = Z_BULKWRITECOMMAND_OBJ_P (getThis ());
404628
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 );
407710}
408711
409712/* MongoDB\Driver\BulkWriteCommand object handlers */
0 commit comments