@@ -590,48 +590,84 @@ int phongo_execute_query(mongoc_client_t *client, const char *namespace, zval *z
590
590
return true;
591
591
} /* }}} */
592
592
593
+ static bson_t * create_wrapped_command_envelope (const char * db , bson_t * reply )
594
+ {
595
+ bson_t * tmp ;
596
+ size_t max_ns_len = strlen (db ) + 5 + 1 ; /* db + ".$cmd" + '\0' */
597
+ char * ns = emalloc (max_ns_len );
598
+
599
+ snprintf (ns , max_ns_len , "%s.$cmd" , db );
600
+ tmp = BCON_NEW ("cursor" , "{" , "id" , BCON_INT64 (0 ), "ns" , BCON_UTF8 (ns ), "firstBatch" , "[" , BCON_DOCUMENT (reply ), "]" , "}" );
601
+ efree (ns );
602
+
603
+ return tmp ;
604
+ }
605
+
593
606
int phongo_execute_command (mongoc_client_t * client , const char * db , zval * zcommand , zval * zreadPreference , int server_id , zval * return_value , int return_value_used TSRMLS_DC ) /* {{{ */
594
607
{
595
608
const php_phongo_command_t * command ;
596
- mongoc_cursor_t * cursor ;
597
609
bson_iter_t iter ;
610
+ bson_t reply ;
611
+ bson_error_t error ;
612
+ bson_t * opts ;
613
+ mongoc_cursor_t * cmd_cursor ;
614
+ uint32_t selected_server_id ;
598
615
599
616
command = Z_COMMAND_OBJ_P (zcommand );
600
617
601
- cursor = mongoc_client_command (client , db , MONGOC_QUERY_NONE , 0 , 1 , 0 , command -> bson , NULL , phongo_read_preference_from_zval (zreadPreference TSRMLS_CC ));
618
+ opts = bson_new ();
619
+ if (server_id > 0 ) {
620
+ bson_append_int32 (opts , "serverId" , -1 , server_id );
621
+ selected_server_id = server_id ;
622
+ } else {
623
+ mongoc_server_description_t * selected_server = NULL ;
602
624
603
- if (server_id > 0 && !mongoc_cursor_set_hint (cursor , server_id )) {
604
- phongo_throw_exception (PHONGO_ERROR_MONGOC_FAILED TSRMLS_CC , "%s" , "Could not set cursor server_id" );
605
- return false;
625
+ selected_server = mongoc_client_select_server (client , false, (zreadPreference ? phongo_read_preference_from_zval (zreadPreference TSRMLS_CC ) : mongoc_client_get_read_prefs (client )), & error );
626
+ if (selected_server ) {
627
+ selected_server_id = mongoc_server_description_id (selected_server );
628
+ bson_append_int32 (opts , "serverId" , -1 , selected_server_id );
629
+ mongoc_server_description_destroy (selected_server );
630
+ } else {
631
+ /* Check for connection related exceptions */
632
+ if (!EG (exception )) {
633
+ phongo_throw_exception_from_bson_error_t (& error TSRMLS_CC );
634
+ }
635
+
636
+ bson_free (opts );
637
+ return false;
638
+ }
606
639
}
607
640
608
- if (!phongo_advance_cursor_and_check_for_error (cursor TSRMLS_CC )) {
641
+ if (!mongoc_client_command_with_opts (client , db , command -> bson , phongo_read_preference_from_zval (zreadPreference TSRMLS_CC ), opts , & reply , & error )) {
642
+ phongo_throw_exception_from_bson_error_t (& error TSRMLS_CC );
643
+ bson_free (opts );
609
644
return false;
610
645
}
611
646
647
+ bson_free (opts );
648
+
612
649
if (!return_value_used ) {
613
- mongoc_cursor_destroy ( cursor );
650
+ bson_destroy ( & reply );
614
651
return true;
615
652
}
616
653
617
- if (bson_iter_init_find (& iter , mongoc_cursor_current (cursor ), "cursor" ) && BSON_ITER_HOLDS_DOCUMENT (& iter )) {
618
- mongoc_cursor_t * cmd_cursor ;
619
-
620
- /* According to mongoc_cursor_new_from_command_reply(), the reply bson_t
621
- * is ultimately destroyed on both success and failure. Use bson_copy()
622
- * to create a writable copy of the const bson_t we fetched above. */
623
- cmd_cursor = mongoc_cursor_new_from_command_reply (client , bson_copy (mongoc_cursor_current (cursor )), mongoc_cursor_get_hint (cursor ));
624
- mongoc_cursor_destroy (cursor );
654
+ /* According to mongoc_cursor_new_from_command_reply(), the reply bson_t
655
+ * is ultimately destroyed on both success and failure. */
656
+ if (bson_iter_init_find (& iter , & reply , "cursor" ) && BSON_ITER_HOLDS_DOCUMENT (& iter )) {
657
+ cmd_cursor = mongoc_cursor_new_from_command_reply (client , & reply , selected_server_id );
658
+ } else {
659
+ bson_t * wrapped_reply = create_wrapped_command_envelope (db , & reply );
625
660
626
- if (! phongo_advance_cursor_and_check_for_error ( cmd_cursor TSRMLS_CC )) {
627
- return false ;
628
- }
661
+ cmd_cursor = mongoc_cursor_new_from_command_reply ( client , wrapped_reply , selected_server_id );
662
+ bson_destroy ( & reply ) ;
663
+ }
629
664
630
- phongo_cursor_init_for_command (return_value , client , cmd_cursor , db , zcommand , zreadPreference TSRMLS_CC );
631
- return true;
665
+ if (!phongo_advance_cursor_and_check_for_error (cmd_cursor TSRMLS_CC )) {
666
+ mongoc_cursor_destroy (cmd_cursor );
667
+ return false;
632
668
}
633
669
634
- phongo_cursor_init_for_command (return_value , client , cursor , db , zcommand , zreadPreference TSRMLS_CC );
670
+ phongo_cursor_init_for_command (return_value , client , cmd_cursor , db , zcommand , zreadPreference TSRMLS_CC );
635
671
return true;
636
672
} /* }}} */
637
673
0 commit comments