@@ -749,7 +749,7 @@ bool phongo_cursor_advance_and_check_for_error(mongoc_cursor_t *cursor TSRMLS_DC
749749 return true;
750750} /* }}} */
751751
752- 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 ) /* {{{ */
752+ 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 ) /* {{{ */
753753{
754754 const php_phongo_query_t * query ;
755755 mongoc_cursor_t * cursor ;
@@ -827,7 +827,29 @@ static bson_t *create_wrapped_command_envelope(const char *db, bson_t *reply)
827827 return tmp ;
828828}
829829
830- 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 ) /* {{{ */
830+ static zval * phongo_create_implicit_session (mongoc_client_t * client TSRMLS_DC ) /* {{{ */
831+ {
832+ mongoc_client_session_t * cs ;
833+ zval * zsession ;
834+
835+ cs = mongoc_client_start_session (client , NULL , NULL );
836+
837+ if (!cs ) {
838+ return NULL ;
839+ }
840+
841+ #if PHP_VERSION_ID >= 70000
842+ zsession = ecalloc (sizeof (zval ), 1 );
843+ #else
844+ ALLOC_INIT_ZVAL (zsession );
845+ #endif
846+
847+ phongo_session_init (zsession , cs TSRMLS_CC );
848+
849+ return zsession ;
850+ } /* }}} */
851+
852+ 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 ) /* {{{ */
831853{
832854 const php_phongo_command_t * command ;
833855 bson_iter_t iter ;
@@ -837,38 +859,50 @@ int phongo_execute_command(mongoc_client_t *client, php_phongo_command_type_t ty
837859 mongoc_cursor_t * cmd_cursor ;
838860 zval * zreadPreference = NULL ;
839861 zval * zsession = NULL ;
840- int result ;
862+ bool result = false;
863+ bool free_reply = false;
864+ bool free_zsession = false;
841865
842866 command = Z_COMMAND_OBJ_P (zcommand );
843867
844868 if ((type & PHONGO_OPTION_READ_CONCERN ) && !phongo_parse_read_concern (options , & opts TSRMLS_CC )) {
845869 /* Exception should already have been thrown */
846- bson_destroy (& opts );
847- return false;
870+ goto cleanup ;
848871 }
849872
850873 if ((type & PHONGO_OPTION_READ_PREFERENCE ) && !phongo_parse_read_preference (options , & zreadPreference TSRMLS_CC )) {
851874 /* Exception should already have been thrown */
852- bson_destroy (& opts );
853- return false;
875+ goto cleanup ;
854876 }
855877
856878 if (!phongo_parse_session (options , client , & opts , & zsession TSRMLS_CC )) {
857879 /* Exception should already have been thrown */
858- bson_destroy (& opts );
859- return false;
880+ goto cleanup ;
881+ }
882+
883+ /* If an explicit session was not provided, attempt to create an implicit
884+ * client session (ignoring any errors). */
885+ if (!zsession ) {
886+ zsession = phongo_create_implicit_session (client TSRMLS_CC );
887+
888+ if (zsession ) {
889+ free_zsession = true;
890+
891+ if (!mongoc_client_session_append (Z_SESSION_OBJ_P (zsession )-> client_session , & opts , NULL )) {
892+ phongo_throw_exception (PHONGO_ERROR_INVALID_ARGUMENT TSRMLS_CC , "Error appending implicit \"sessionId\" option" );
893+ goto cleanup ;
894+ }
895+ }
860896 }
861897
862898 if ((type & PHONGO_OPTION_WRITE_CONCERN ) && !phongo_parse_write_concern (options , & opts , NULL TSRMLS_CC )) {
863899 /* Exception should already have been thrown */
864- bson_destroy (& opts );
865- return false;
900+ goto cleanup ;
866901 }
867902
868903 if (!BSON_APPEND_INT32 (& opts , "serverId" , server_id )) {
869904 phongo_throw_exception (PHONGO_ERROR_INVALID_ARGUMENT TSRMLS_CC , "Error appending \"serverId\" option" );
870- bson_destroy (& opts );
871- return false;
905+ goto cleanup ;
872906 }
873907
874908 /* Although "opts" already always includes the serverId option, the read
@@ -891,27 +925,25 @@ int phongo_execute_command(mongoc_client_t *client, php_phongo_command_type_t ty
891925 default :
892926 /* Should never happen, but if it does: exception */
893927 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 );
894- bson_destroy (& opts );
895- return false;
928+ goto cleanup ;
896929 }
930+
931+ free_reply = true;
932+
897933 if (!result ) {
898934 phongo_throw_exception_from_bson_error_t (& error TSRMLS_CC );
899- bson_destroy (& reply );
900- bson_destroy (& opts );
901- return false;
935+ goto cleanup ;
902936 }
903937
904- bson_destroy (& opts );
905-
906938 if (!return_value_used ) {
907- bson_destroy (& reply );
908- return true;
939+ goto cleanup ;
909940 }
910941
911942 /* According to mongoc_cursor_new_from_command_reply(), the reply bson_t
912943 * is ultimately destroyed on both success and failure. */
913944 if (bson_iter_init_find (& iter , & reply , "cursor" ) && BSON_ITER_HOLDS_DOCUMENT (& iter )) {
914945 bson_t initial_reply = BSON_INITIALIZER ;
946+ bson_error_t error = {0 };
915947
916948 bson_copy_to (& reply , & initial_reply );
917949
@@ -925,17 +957,39 @@ int phongo_execute_command(mongoc_client_t *client, php_phongo_command_type_t ty
925957 bson_append_int64 (& initial_reply , "batchSize" , -1 , command -> batch_size );
926958 }
927959
960+ if (zsession && !mongoc_client_session_append (Z_SESSION_OBJ_P (zsession )-> client_session , & initial_reply , & error )) {
961+ phongo_throw_exception_from_bson_error_t (& error TSRMLS_CC );
962+ bson_destroy (& initial_reply );
963+ result = false;
964+ goto cleanup ;
965+ }
966+
928967 cmd_cursor = mongoc_cursor_new_from_command_reply (client , & initial_reply , server_id );
929- bson_destroy (& reply );
930968 } else {
931969 bson_t * wrapped_reply = create_wrapped_command_envelope (db , & reply );
932970
933971 cmd_cursor = mongoc_cursor_new_from_command_reply (client , wrapped_reply , server_id );
934- bson_destroy (& reply );
935972 }
936973
937974 phongo_cursor_init_for_command (return_value , client , cmd_cursor , db , zcommand , zreadPreference , zsession TSRMLS_CC );
938- return true;
975+
976+ cleanup :
977+ bson_destroy (& opts );
978+
979+ if (free_reply ) {
980+ bson_destroy (& reply );
981+ }
982+
983+ if (free_zsession ) {
984+ #if PHP_VERSION_ID >= 70000
985+ zval_ptr_dtor (zsession );
986+ efree (zsession );
987+ #else
988+ zval_ptr_dtor (& zsession );
989+ #endif
990+ }
991+
992+ return result ;
939993} /* }}} */
940994/* }}} */
941995
0 commit comments