@@ -569,9 +569,34 @@ bool phongo_execute_write(mongoc_client_t *client, const char *namespace, mongoc
569
569
return success ;
570
570
} /* }}} */
571
571
572
+ /* Advance the cursor and return whether there is an error. On error, the cursor
573
+ * will be destroyed and an exception will be thrown. */
574
+ static bool phongo_advance_cursor_and_check_for_error (mongoc_cursor_t * cursor TSRMLS_DC )
575
+ {
576
+ const bson_t * doc ;
577
+
578
+ if (!mongoc_cursor_next (cursor , & doc )) {
579
+ bson_error_t error ;
580
+
581
+ /* Check for connection related exceptions */
582
+ if (EG (exception )) {
583
+ mongoc_cursor_destroy (cursor );
584
+ return false;
585
+ }
586
+
587
+ /* Could simply be no docs, which is not an error */
588
+ if (mongoc_cursor_error (cursor , & error )) {
589
+ phongo_throw_exception_from_bson_error_t (& error TSRMLS_CC );
590
+ mongoc_cursor_destroy (cursor );
591
+ return false;
592
+ }
593
+ }
594
+
595
+ return true;
596
+ }
597
+
572
598
int phongo_execute_query (mongoc_client_t * client , const char * namespace , const php_phongo_query_t * query , const mongoc_read_prefs_t * read_preference , int server_id , zval * return_value , int return_value_used TSRMLS_DC ) /* {{{ */
573
599
{
574
- const bson_t * doc = NULL ;
575
600
mongoc_cursor_t * cursor ;
576
601
char * dbname ;
577
602
char * collname ;
@@ -601,22 +626,9 @@ int phongo_execute_query(mongoc_client_t *client, const char *namespace, const p
601
626
if (server_id > 0 ) {
602
627
cursor -> server_id = server_id ;
603
628
}
604
- if (!mongoc_cursor_next (cursor , & doc )) {
605
- bson_error_t error ;
606
-
607
- /* Check for connection related exceptions */
608
- if (EG (exception )) {
609
- mongoc_cursor_destroy (cursor );
610
- return false;
611
- }
612
-
613
- /* Could simply be no docs, which is not an error */
614
- if (mongoc_cursor_error (cursor , & error )) {
615
- phongo_throw_exception_from_bson_error_t (& error TSRMLS_CC );
616
- mongoc_cursor_destroy (cursor );
617
- return false;
618
- }
619
629
630
+ if (!phongo_advance_cursor_and_check_for_error (cursor TSRMLS_CC )) {
631
+ return false;
620
632
}
621
633
622
634
if (!return_value_used ) {
@@ -631,73 +643,38 @@ int phongo_execute_query(mongoc_client_t *client, const char *namespace, const p
631
643
int phongo_execute_command (mongoc_client_t * client , const char * db , const bson_t * command , const mongoc_read_prefs_t * read_preference , int server_id , zval * return_value , int return_value_used TSRMLS_DC ) /* {{{ */
632
644
{
633
645
mongoc_cursor_t * cursor ;
634
- const bson_t * doc ;
635
646
bson_iter_t iter ;
636
- bson_iter_t child ;
637
647
638
648
639
649
cursor = mongoc_client_command (client , db , MONGOC_QUERY_NONE , 0 , 1 , 0 , command , NULL , read_preference );
640
650
if (server_id > 0 ) {
641
651
cursor -> server_id = server_id ;
642
652
}
643
653
644
- if (!mongoc_cursor_next (cursor , & doc )) {
645
- bson_error_t error ;
646
-
647
- /* Check for connection related exceptions */
648
- if (EG (exception )) {
649
- mongoc_cursor_destroy (cursor );
650
- return false;
651
- }
652
-
653
- if (mongoc_cursor_error (cursor , & error )) {
654
- mongoc_cursor_destroy (cursor );
655
- phongo_throw_exception_from_bson_error_t (& error TSRMLS_CC );
656
- return false;
657
- }
654
+ if (!phongo_advance_cursor_and_check_for_error (cursor TSRMLS_CC )) {
655
+ return false;
658
656
}
659
657
660
658
if (!return_value_used ) {
661
659
mongoc_cursor_destroy (cursor );
662
660
return true;
663
661
}
664
662
665
- /* This code is adapated from _mongoc_cursor_cursorid_prime(), but we avoid
666
- * advancing the cursor, since we are already positioned at the first result
667
- * after the error checking above. */
668
- if (bson_iter_init_find (& iter , doc , "cursor" ) && BSON_ITER_HOLDS_DOCUMENT (& iter ) && bson_iter_recurse (& iter , & child )) {
669
- mongoc_cursor_cursorid_t * cid ;
670
- bson_t empty = BSON_INITIALIZER ;
671
-
672
- _mongoc_cursor_cursorid_init (cursor , & empty );
673
- cursor -> limit = 0 ;
663
+ if (bson_iter_init_find (& iter , mongoc_cursor_current (cursor ), "cursor" ) && BSON_ITER_HOLDS_DOCUMENT (& iter )) {
664
+ mongoc_cursor_t * cmd_cursor ;
674
665
675
- cid = cursor -> iface_data ;
676
- cid -> in_batch = true;
677
- bson_destroy (& empty );
678
-
679
- while (bson_iter_next (& child )) {
680
- if (BSON_ITER_IS_KEY (& child , "id" )) {
681
- cursor -> rpc .reply .cursor_id = bson_iter_as_int64 (& child );
682
- } else if (BSON_ITER_IS_KEY (& child , "ns" )) {
683
- const char * ns ;
666
+ /* According to mongoc_cursor_new_from_command_reply(), the reply bson_t
667
+ * is ultimately destroyed on both success and failure. Use bson_copy()
668
+ * to create a writable copy of the const bson_t we fetched above. */
669
+ cmd_cursor = mongoc_cursor_new_from_command_reply (client , bson_copy (mongoc_cursor_current (cursor )), mongoc_cursor_get_hint (cursor ));
670
+ mongoc_cursor_destroy (cursor );
684
671
685
- ns = bson_iter_utf8 (& child , & cursor -> nslen );
686
- bson_strncpy (cursor -> ns , ns , sizeof cursor -> ns );
687
- } else if (BSON_ITER_IS_KEY (& child , "firstBatch" )) {
688
- if (BSON_ITER_HOLDS_ARRAY (& child ) && bson_iter_recurse (& child , & cid -> batch_iter )) {
689
- cid -> in_batch = true;
690
- }
691
- }
672
+ if (!phongo_advance_cursor_and_check_for_error (cmd_cursor TSRMLS_CC )) {
673
+ return false;
692
674
}
693
675
694
- cursor -> is_command = false;
695
-
696
- /* The cursor's current element is the command's response document.
697
- * Advance once so that the cursor is positioned at the first document
698
- * within the command cursor's result set.
699
- */
700
- mongoc_cursor_next (cursor , & doc );
676
+ phongo_cursor_init (return_value , cmd_cursor , client TSRMLS_CC );
677
+ return true;
701
678
}
702
679
703
680
phongo_cursor_init (return_value , cursor , client TSRMLS_CC );
0 commit comments