Skip to content

Commit 59b7d90

Browse files
committed
wip PHPC-2493: BulkWriteCommand::execute()
1 parent 2e54ade commit 59b7d90

File tree

6 files changed

+140
-3
lines changed

6 files changed

+140
-3
lines changed

src/MongoDB/BulkWriteCommand.c

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,34 @@
3434

3535
zend_class_entry* php_phongo_bulkwritecommand_ce;
3636

37+
/* Creates a mongoc_bulkwriteopts_t from internal options, which should be freed
38+
* by the caller. */
39+
mongoc_bulkwriteopts_t* phongo_bwc_assemble_opts(php_phongo_bulkwritecommand_t* intern)
40+
{
41+
mongoc_bulkwriteopts_t* opts = mongoc_bulkwriteopts_new();
42+
43+
if (intern->bypass != PHONGO_BULKWRITECOMMAND_BYPASS_UNSET) {
44+
mongoc_bulkwriteopts_set_bypassdocumentvalidation(opts, intern->bypass);
45+
}
46+
47+
if (intern->comment) {
48+
mongoc_bulkwriteopts_set_comment(opts, intern->comment);
49+
}
50+
51+
if (intern->let) {
52+
mongoc_bulkwriteopts_set_let(opts, intern->let);
53+
}
54+
55+
mongoc_bulkwriteopts_set_ordered(opts, intern->ordered);
56+
mongoc_bulkwriteopts_set_verboseresults(opts, intern->verbose);
57+
58+
if (intern->write_concern) {
59+
mongoc_bulkwriteopts_set_writeconcern(opts, intern->write_concern);
60+
}
61+
62+
return opts;
63+
}
64+
3765
// TODO: Make this a common utility function to share with BulkWrite.c
3866
/* Extracts the "_id" field of a BSON document into a return value. */
3967
static void phongo_bwc_extract_id(bson_t* doc, zval** return_value)

src/MongoDB/BulkWriteCommand.h

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
/*
2+
* Copyright 2024-present MongoDB, Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
#ifndef PHONGO_BULKWRITECOMMAND_H
18+
#define PHONGO_BULKWRITECOMMAND_H
19+
20+
#include "mongoc/mongoc.h"
21+
22+
#include "phongo_structs.h"
23+
24+
mongoc_bulkwriteopts_t* phongo_bwc_assemble_opts(php_phongo_bulkwritecommand_t* intern);
25+
26+
#endif /* PHONGO_BULKWRITECOMMAND_H */

src/MongoDB/BulkWriteCommand.stub.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,5 +26,5 @@ final public function updateOne(string $namespace, array|object $filter, array|o
2626

2727
final public function updateMany(string $namespace, array|object $filter, array|object $update, ?array $options = null): void {}
2828

29-
final public function execute(Manager|Server $managerOrServer): mixed {}
29+
final public function execute(Manager|Server $managerOrServer, ?array $options = null): ?BulkWriteCommandResult {}
3030
}

src/MongoDB/BulkWriteCommand_arginfo.h

Lines changed: 3 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/phongo_execute.c

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@
2727
#include "phongo_execute.h"
2828
#include "phongo_util.h"
2929

30+
#include "MongoDB/BulkWriteCommand.h"
31+
#include "MongoDB/BulkWriteCommandResult.h"
3032
#include "MongoDB/Cursor.h"
3133
#include "MongoDB/ReadPreference.h"
3234
#include "MongoDB/Session.h"
@@ -333,6 +335,83 @@ bool phongo_execute_bulk_write(zval* manager, const char* namespace, php_phongo_
333335
return success;
334336
}
335337

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+
336415
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)
337416
{
338417
mongoc_client_t* client;

src/phongo_execute.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222

2323
#include <php.h>
2424

25+
#include "phongo_structs.h"
26+
2527
/* This enum is used for processing options and selecting a libmongoc function
2628
* to use in phongo_execute_command. The values are important, as READ and WRITE
2729
* are also used as a bit field to determine whether readPreference,
@@ -37,6 +39,7 @@ typedef enum {
3739
} php_phongo_command_type_t;
3840

3941
bool phongo_execute_bulk_write(zval* manager, const char* namespace, php_phongo_bulkwrite_t* bulk_write, zval* zwriteConcern, uint32_t server_id, zval* return_value);
42+
bool phongo_execute_bulkwritecommand(zval* manager, php_phongo_bulkwritecommand_t* bwc, zval* zoptions, uint32_t server_id, zval* return_value);
4043
bool phongo_execute_command(zval* manager, php_phongo_command_type_t type, const char* db, zval* zcommand, zval* zreadPreference, uint32_t server_id, zval* return_value);
4144
bool phongo_execute_query(zval* manager, const char* namespace, zval* zquery, zval* zreadPreference, uint32_t server_id, zval* return_value);
4245

0 commit comments

Comments
 (0)