@@ -719,7 +719,7 @@ bool phongo_cursor_advance_and_check_for_error(mongoc_cursor_t* cursor TSRMLS_DC
719
719
return true;
720
720
} /* }}} */
721
721
722
- int phongo_execute_query (mongoc_client_t * client , const char * namespace , zval * zquery , zval * options , uint32_t server_id , zval * return_value , int return_value_used TSRMLS_DC ) /* {{{ */
722
+ bool phongo_execute_query (mongoc_client_t * client , const char * namespace , zval * zquery , zval * options , uint32_t server_id , zval * return_value , int return_value_used TSRMLS_DC ) /* {{{ */
723
723
{
724
724
const php_phongo_query_t * query ;
725
725
mongoc_cursor_t * cursor ;
@@ -797,7 +797,29 @@ static bson_t* create_wrapped_command_envelope(const char* db, bson_t* reply)
797
797
return tmp ;
798
798
}
799
799
800
- int phongo_execute_command (mongoc_client_t * client , php_phongo_command_type_t type , const char * db , zval * zcommand , zval * options , uint32_t server_id , zval * return_value , int return_value_used TSRMLS_DC ) /* {{{ */
800
+ static zval * phongo_create_implicit_session (mongoc_client_t * client TSRMLS_DC ) /* {{{ */
801
+ {
802
+ mongoc_client_session_t * cs ;
803
+ zval * zsession ;
804
+
805
+ cs = mongoc_client_start_session (client , NULL , NULL );
806
+
807
+ if (!cs ) {
808
+ return NULL ;
809
+ }
810
+
811
+ #if PHP_VERSION_ID >= 70000
812
+ zsession = ecalloc (sizeof (zval ), 1 );
813
+ #else
814
+ ALLOC_INIT_ZVAL (zsession );
815
+ #endif
816
+
817
+ phongo_session_init (zsession , cs TSRMLS_CC );
818
+
819
+ return zsession ;
820
+ } /* }}} */
821
+
822
+ bool phongo_execute_command (mongoc_client_t * client , php_phongo_command_type_t type , const char * db , zval * zcommand , zval * options , uint32_t server_id , zval * return_value , int return_value_used TSRMLS_DC ) /* {{{ */
801
823
{
802
824
const php_phongo_command_t * command ;
803
825
bson_iter_t iter ;
@@ -807,38 +829,50 @@ int phongo_execute_command(mongoc_client_t* client, php_phongo_command_type_t ty
807
829
mongoc_cursor_t * cmd_cursor ;
808
830
zval * zreadPreference = NULL ;
809
831
zval * zsession = NULL ;
810
- int result ;
832
+ bool result = false;
833
+ bool free_reply = false;
834
+ bool free_zsession = false;
811
835
812
836
command = Z_COMMAND_OBJ_P (zcommand );
813
837
814
838
if ((type & PHONGO_OPTION_READ_CONCERN ) && !phongo_parse_read_concern (options , & opts TSRMLS_CC )) {
815
839
/* Exception should already have been thrown */
816
- bson_destroy (& opts );
817
- return false;
840
+ goto cleanup ;
818
841
}
819
842
820
843
if ((type & PHONGO_OPTION_READ_PREFERENCE ) && !phongo_parse_read_preference (options , & zreadPreference TSRMLS_CC )) {
821
844
/* Exception should already have been thrown */
822
- bson_destroy (& opts );
823
- return false;
845
+ goto cleanup ;
824
846
}
825
847
826
848
if (!phongo_parse_session (options , client , & opts , & zsession TSRMLS_CC )) {
827
849
/* Exception should already have been thrown */
828
- bson_destroy (& opts );
829
- return false;
850
+ goto cleanup ;
851
+ }
852
+
853
+ /* If an explicit session was not provided, attempt to create an implicit
854
+ * client session (ignoring any errors). */
855
+ if (!zsession ) {
856
+ zsession = phongo_create_implicit_session (client TSRMLS_CC );
857
+
858
+ if (zsession ) {
859
+ free_zsession = true;
860
+
861
+ if (!mongoc_client_session_append (Z_SESSION_OBJ_P (zsession )-> client_session , & opts , NULL )) {
862
+ phongo_throw_exception (PHONGO_ERROR_INVALID_ARGUMENT TSRMLS_CC , "Error appending implicit \"sessionId\" option" );
863
+ goto cleanup ;
864
+ }
865
+ }
830
866
}
831
867
832
868
if ((type & PHONGO_OPTION_WRITE_CONCERN ) && !phongo_parse_write_concern (options , & opts , NULL TSRMLS_CC )) {
833
869
/* Exception should already have been thrown */
834
- bson_destroy (& opts );
835
- return false;
870
+ goto cleanup ;
836
871
}
837
872
838
873
if (!BSON_APPEND_INT32 (& opts , "serverId" , server_id )) {
839
874
phongo_throw_exception (PHONGO_ERROR_INVALID_ARGUMENT TSRMLS_CC , "Error appending \"serverId\" option" );
840
- bson_destroy (& opts );
841
- return false;
875
+ goto cleanup ;
842
876
}
843
877
844
878
/* Although "opts" already always includes the serverId option, the read
@@ -861,9 +895,11 @@ int phongo_execute_command(mongoc_client_t* client, php_phongo_command_type_t ty
861
895
default :
862
896
/* Should never happen, but if it does: exception */
863
897
phongo_throw_exception (PHONGO_ERROR_LOGIC TSRMLS_CC , "Type '%d' should never have been passed to phongo_execute_command, please file a bug report" , type );
864
- bson_destroy (& opts );
865
- return false;
898
+ goto cleanup ;
866
899
}
900
+
901
+ free_reply = true;
902
+
867
903
if (!result ) {
868
904
/* Server errors (other than ExceededTimeLimit) and write concern errors
869
905
* may use CommandException and report the result document for the
@@ -888,22 +924,18 @@ int phongo_execute_command(mongoc_client_t* client, php_phongo_command_type_t ty
888
924
} else {
889
925
phongo_throw_exception_from_bson_error_t (& error TSRMLS_CC );
890
926
}
891
- bson_destroy (& reply );
892
- bson_destroy (& opts );
893
- return false;
927
+ goto cleanup ;
894
928
}
895
929
896
- bson_destroy (& opts );
897
-
898
930
if (!return_value_used ) {
899
- bson_destroy (& reply );
900
- return true;
931
+ goto cleanup ;
901
932
}
902
933
903
934
/* According to mongoc_cursor_new_from_command_reply(), the reply bson_t
904
935
* is ultimately destroyed on both success and failure. */
905
936
if (bson_iter_init_find (& iter , & reply , "cursor" ) && BSON_ITER_HOLDS_DOCUMENT (& iter )) {
906
937
bson_t initial_reply = BSON_INITIALIZER ;
938
+ bson_error_t error = {0 };
907
939
908
940
bson_copy_to (& reply , & initial_reply );
909
941
@@ -917,17 +949,39 @@ int phongo_execute_command(mongoc_client_t* client, php_phongo_command_type_t ty
917
949
bson_append_int64 (& initial_reply , "batchSize" , -1 , command -> batch_size );
918
950
}
919
951
952
+ if (zsession && !mongoc_client_session_append (Z_SESSION_OBJ_P (zsession )-> client_session , & initial_reply , & error )) {
953
+ phongo_throw_exception_from_bson_error_t (& error TSRMLS_CC );
954
+ bson_destroy (& initial_reply );
955
+ result = false;
956
+ goto cleanup ;
957
+ }
958
+
920
959
cmd_cursor = mongoc_cursor_new_from_command_reply (client , & initial_reply , server_id );
921
- bson_destroy (& reply );
922
960
} else {
923
961
bson_t * wrapped_reply = create_wrapped_command_envelope (db , & reply );
924
962
925
963
cmd_cursor = mongoc_cursor_new_from_command_reply (client , wrapped_reply , server_id );
926
- bson_destroy (& reply );
927
964
}
928
965
929
966
phongo_cursor_init_for_command (return_value , client , cmd_cursor , db , zcommand , zreadPreference , zsession TSRMLS_CC );
930
- return true;
967
+
968
+ cleanup :
969
+ bson_destroy (& opts );
970
+
971
+ if (free_reply ) {
972
+ bson_destroy (& reply );
973
+ }
974
+
975
+ if (free_zsession ) {
976
+ #if PHP_VERSION_ID >= 70000
977
+ zval_ptr_dtor (zsession );
978
+ efree (zsession );
979
+ #else
980
+ zval_ptr_dtor (& zsession );
981
+ #endif
982
+ }
983
+
984
+ return result ;
931
985
} /* }}} */
932
986
/* }}} */
933
987
0 commit comments