|
27 | 27 | #include "phongo_execute.h"
|
28 | 28 | #include "phongo_util.h"
|
29 | 29 |
|
| 30 | +#include "MongoDB/BulkWriteCommand.h" |
| 31 | +#include "MongoDB/BulkWriteCommandResult.h" |
30 | 32 | #include "MongoDB/Cursor.h"
|
31 | 33 | #include "MongoDB/ReadPreference.h"
|
32 | 34 | #include "MongoDB/Session.h"
|
@@ -333,6 +335,83 @@ bool phongo_execute_bulk_write(zval* manager, const char* namespace, php_phongo_
|
333 | 335 | return success;
|
334 | 336 | }
|
335 | 337 |
|
| 338 | +bool phongo_execute_bulkwritecommand(zval* manager, php_phongo_bulkwritecommand_t* bwc, zval* zoptions, uint32_t server_id, zval* return_value) |
| 339 | +{ |
| 340 | + mongoc_client_t* client = NULL; |
| 341 | + mongoc_bulkwrite_t* bw = bwc->bw; |
| 342 | + mongoc_bulkwriteopts_t* bw_opts = NULL; |
| 343 | + mongoc_bulkwritereturn_t bw_ret = { 0 }; |
| 344 | + php_phongo_bulkwritecommandresult_t* bwcr; |
| 345 | + zval* zsession = NULL; |
| 346 | + bool success = true; |
| 347 | + |
| 348 | + client = Z_MANAGER_OBJ_P(manager)->client; |
| 349 | + |
| 350 | + if (!phongo_parse_session(zoptions, client, NULL, &zsession)) { |
| 351 | + /* Exception should already have been thrown */ |
| 352 | + return false; |
| 353 | + } |
| 354 | + |
| 355 | + mongoc_bulkwrite_set_client(bw, client); |
| 356 | + |
| 357 | + bw_opts = phongo_bwc_assemble_opts(bwc); |
| 358 | + mongoc_bulkwriteopts_set_serverid(bw_opts, server_id); |
| 359 | + |
| 360 | + if (zsession) { |
| 361 | + mongoc_bulkwrite_set_session(bw, Z_SESSION_OBJ_P(zsession)->client_session); |
| 362 | + /* Save a reference to the session on the class struct to avoid leaving |
| 363 | + * a dangling pointer within mongoc_bulkwrite_t. */ |
| 364 | + ZVAL_ZVAL(&bwc->session, zsession, 1, 0); |
| 365 | + } |
| 366 | + |
| 367 | + bw_ret = mongoc_bulkwrite_execute(bw, bw_opts); |
| 368 | + |
| 369 | + bwcr = phongo_bulkwritecommandresult_init(return_value, &bw_ret, manager); |
| 370 | + |
| 371 | + if (bw_ret.exc) { |
| 372 | + success = false; |
| 373 | + bson_error_t error = { 0 }; |
| 374 | + |
| 375 | + // Check if there is a top-level error |
| 376 | + if (mongoc_bulkwriteexception_error(bw_ret.exc, &error)) { |
| 377 | + phongo_throw_exception_from_bson_error_t_and_reply(&error, mongoc_bulkwriteexception_errorreply(bw_ret.exc)); |
| 378 | + } else { |
| 379 | + // TODO: Determine appropriate message w/o top-level error |
| 380 | + zend_throw_exception(php_phongo_bulkwritecommandexception_ce, "Bulk write failed", 0); |
| 381 | + } |
| 382 | + |
| 383 | + /* Unlike mongoc_bulk_operation_execute, mongoc_bulkwrite_execute may |
| 384 | + * report COMMAND_INVALID_ARG alongside a partial result (CDRIVER-5842). |
| 385 | + * If there is no result, we can throw InvalidArgumentException without |
| 386 | + * proxying it behind a BulkWriteException. */ |
| 387 | + if (!bw_ret.res && error.domain == MONGOC_ERROR_COMMAND && error.code == MONGOC_ERROR_COMMAND_INVALID_ARG) { |
| 388 | + // TODO: Do we care about other mongoc_bulkwriteexception_t fields? |
| 389 | + goto cleanup; |
| 390 | + } |
| 391 | + |
| 392 | + if (EG(exception)) { |
| 393 | + char* message; |
| 394 | + |
| 395 | + (void) spprintf(&message, 0, "Bulk write failed due to previous %s: %s", PHONGO_ZVAL_EXCEPTION_NAME(EG(exception)), error.message); |
| 396 | + zend_throw_exception(php_phongo_bulkwritecommandexception_ce, message, 0); |
| 397 | + efree(message); |
| 398 | + } |
| 399 | + |
| 400 | + /* Ensure error labels are added to the final BulkWriteCommandException. If a |
| 401 | + * previous exception was also thrown, error labels will already have |
| 402 | + * been added by phongo_throw_exception_from_bson_error_t_and_reply. */ |
| 403 | + phongo_exception_add_error_labels(mongoc_bulkwriteexception_errorreply(bw_ret.exc)); |
| 404 | + phongo_add_exception_prop(ZEND_STRL("bulkWriteCommandResult"), return_value); |
| 405 | + } |
| 406 | + |
| 407 | +cleanup: |
| 408 | + mongoc_bulkwriteopts_destroy(bw_opts); |
| 409 | + mongoc_bulkwriteresult_destroy(bw_ret.res); |
| 410 | + mongoc_bulkwriteexception_destroy(bw_ret.exc); |
| 411 | + |
| 412 | + return success; |
| 413 | +} |
| 414 | + |
336 | 415 | bool phongo_execute_command(zval* manager, php_phongo_command_type_t type, const char* db, zval* zcommand, zval* options, uint32_t server_id, zval* return_value)
|
337 | 416 | {
|
338 | 417 | mongoc_client_t* client;
|
|
0 commit comments