From 3d52b8d64c9136dcef31e82acae2a2842ce55701 Mon Sep 17 00:00:00 2001 From: Andreas Braun Date: Thu, 24 Nov 2022 14:21:31 +0100 Subject: [PATCH] PHPC-2165: Expose server error replies in BulkWriteResult --- src/MongoDB/WriteResult.c | 46 ++++++++++++++++++- src/MongoDB/WriteResult.stub.php | 2 + src/MongoDB/WriteResult_arginfo.h | 6 ++- ...bulkwriteexception-getwriteresult-001.phpt | 3 ++ .../manager-executeBulkWrite_error-005.phpt | 7 ++- .../replicaset/writeresult-getserver-002.phpt | 3 ++ tests/server/server-executeBulkWrite-001.phpt | 3 ++ .../writeresult-isacknowledged-001.phpt | 3 ++ .../writeresult-isacknowledged-002.phpt | 3 ++ .../writeresult-isacknowledged-003.phpt | 3 ++ tests/writeResult/writeresult-debug-001.phpt | 3 ++ tests/writeResult/writeresult-debug-002.phpt | 3 ++ .../writeresult-getErrorReplies-001.phpt | 40 ++++++++++++++++ 13 files changed, 121 insertions(+), 4 deletions(-) create mode 100644 tests/writeResult/writeresult-getErrorReplies-001.phpt diff --git a/src/MongoDB/WriteResult.c b/src/MongoDB/WriteResult.c index f9736f0e3..6ae5426bb 100644 --- a/src/MongoDB/WriteResult.c +++ b/src/MongoDB/WriteResult.c @@ -117,6 +117,32 @@ static bool php_phongo_writeresult_get_writeerrors(php_phongo_writeresult_t* int return true; } +static bool php_phongo_writeresult_get_error_replies(php_phongo_writeresult_t* intern, zval* return_value) +{ + bson_iter_t iter, child; + + array_init(return_value); + + if (bson_iter_init_find(&iter, intern->reply, "errorReplies") && BSON_ITER_HOLDS_ARRAY(&iter) && bson_iter_recurse(&iter, &child)) { + while (bson_iter_next(&child)) { + uint32_t len; + const uint8_t* data; + zval error_reply; + + if (!BSON_ITER_HOLDS_DOCUMENT(&child)) { + continue; + } + + bson_iter_document(&child, &len, &data); + php_phongo_bson_data_to_zval(data, len, &error_reply); + + add_next_index_zval(return_value, &error_reply); + } + } + + return true; +} + PHONGO_DISABLED_CONSTRUCTOR(MongoDB_Driver_WriteResult) PHONGO_DISABLED_WAKEUP(MongoDB_Driver_WriteResult) @@ -273,6 +299,17 @@ static PHP_METHOD(MongoDB_Driver_WriteResult, getWriteErrors) php_phongo_writeresult_get_writeerrors(intern, return_value); } +static PHP_METHOD(MongoDB_Driver_WriteResult, getErrorReplies) +{ + php_phongo_writeresult_t* intern; + + intern = Z_WRITERESULT_OBJ_P(getThis()); + + PHONGO_PARSE_PARAMETERS_NONE(); + + php_phongo_writeresult_get_error_replies(intern, return_value); +} + /* Returns whether the write operation was acknowledged (based on the write concern). */ static PHP_METHOD(MongoDB_Driver_WriteResult, isAcknowledged) @@ -328,7 +365,7 @@ static HashTable* php_phongo_writeresult_get_debug_info(phongo_compat_object_han intern = Z_OBJ_WRITERESULT(PHONGO_COMPAT_GET_OBJ(object)); *is_temp = 1; - array_init_size(&retval, 9); + array_init_size(&retval, 10); #define PHONGO_WRITERESULT_SCP(field) \ if (bson_iter_init_find(&iter, intern->reply, (field)) && BSON_ITER_HOLDS_INT32(&iter)) { \ @@ -386,6 +423,13 @@ static HashTable* php_phongo_writeresult_get_debug_info(phongo_compat_object_han ADD_ASSOC_NULL_EX(&retval, "writeConcern"); } + { + zval error_replies; + + php_phongo_writeresult_get_error_replies(intern, &error_replies); + ADD_ASSOC_ZVAL_EX(&retval, "errorReplies", &error_replies); + } + done: return Z_ARRVAL(retval); } diff --git a/src/MongoDB/WriteResult.stub.php b/src/MongoDB/WriteResult.stub.php index dfb7766d4..2d114509a 100644 --- a/src/MongoDB/WriteResult.stub.php +++ b/src/MongoDB/WriteResult.stub.php @@ -29,6 +29,8 @@ final public function getWriteConcernError(): ?WriteConcernError {} final public function getWriteErrors(): array {} + final public function getErrorReplies(): array {} + final public function isAcknowledged(): bool {} final public function __wakeup(): void {} diff --git a/src/MongoDB/WriteResult_arginfo.h b/src/MongoDB/WriteResult_arginfo.h index a7e950633..a68c5bc70 100644 --- a/src/MongoDB/WriteResult_arginfo.h +++ b/src/MongoDB/WriteResult_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: eae27215b994b4941296f69331abd6d1a3173df7 */ + * Stub hash: 279a9a00d54bf67c310f7b8802a5868bf1d507eb */ ZEND_BEGIN_ARG_INFO_EX(arginfo_class_MongoDB_Driver_WriteResult___construct, 0, 0, 0) ZEND_END_ARG_INFO() @@ -26,6 +26,8 @@ ZEND_END_ARG_INFO() #define arginfo_class_MongoDB_Driver_WriteResult_getWriteErrors arginfo_class_MongoDB_Driver_WriteResult_getUpsertedIds +#define arginfo_class_MongoDB_Driver_WriteResult_getErrorReplies arginfo_class_MongoDB_Driver_WriteResult_getUpsertedIds + ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_MongoDB_Driver_WriteResult_isAcknowledged, 0, 0, _IS_BOOL, 0) ZEND_END_ARG_INFO() @@ -43,6 +45,7 @@ static ZEND_METHOD(MongoDB_Driver_WriteResult, getServer); static ZEND_METHOD(MongoDB_Driver_WriteResult, getUpsertedIds); static ZEND_METHOD(MongoDB_Driver_WriteResult, getWriteConcernError); static ZEND_METHOD(MongoDB_Driver_WriteResult, getWriteErrors); +static ZEND_METHOD(MongoDB_Driver_WriteResult, getErrorReplies); static ZEND_METHOD(MongoDB_Driver_WriteResult, isAcknowledged); static ZEND_METHOD(MongoDB_Driver_WriteResult, __wakeup); @@ -58,6 +61,7 @@ static const zend_function_entry class_MongoDB_Driver_WriteResult_methods[] = { ZEND_ME(MongoDB_Driver_WriteResult, getUpsertedIds, arginfo_class_MongoDB_Driver_WriteResult_getUpsertedIds, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL) ZEND_ME(MongoDB_Driver_WriteResult, getWriteConcernError, arginfo_class_MongoDB_Driver_WriteResult_getWriteConcernError, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL) ZEND_ME(MongoDB_Driver_WriteResult, getWriteErrors, arginfo_class_MongoDB_Driver_WriteResult_getWriteErrors, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL) + ZEND_ME(MongoDB_Driver_WriteResult, getErrorReplies, arginfo_class_MongoDB_Driver_WriteResult_getErrorReplies, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL) ZEND_ME(MongoDB_Driver_WriteResult, isAcknowledged, arginfo_class_MongoDB_Driver_WriteResult_isAcknowledged, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL) ZEND_ME(MongoDB_Driver_WriteResult, __wakeup, arginfo_class_MongoDB_Driver_WriteResult___wakeup, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL) ZEND_FE_END diff --git a/tests/exception/bulkwriteexception-getwriteresult-001.phpt b/tests/exception/bulkwriteexception-getwriteresult-001.phpt index 419e9c8e1..b2d50cf3e 100644 --- a/tests/exception/bulkwriteexception-getwriteresult-001.phpt +++ b/tests/exception/bulkwriteexception-getwriteresult-001.phpt @@ -56,5 +56,8 @@ object(MongoDB\Driver\WriteResult)#%d (%d) { ["writeConcern"]=> object(MongoDB\Driver\WriteConcern)#%d (%d) { } + ["errorReplies"]=> + array(0) { + } } ===DONE=== diff --git a/tests/manager/manager-executeBulkWrite_error-005.phpt b/tests/manager/manager-executeBulkWrite_error-005.phpt index d97002321..3ce2e6de2 100644 --- a/tests/manager/manager-executeBulkWrite_error-005.phpt +++ b/tests/manager/manager-executeBulkWrite_error-005.phpt @@ -39,7 +39,7 @@ try { --EXPECTF-- MongoDB\Driver\Exception\BulkWriteException(0): Bulk write failed due to previous MongoDB\Driver\Exception\ConnectionTimeoutException: Failed to send "delete" command with database "%s": Failed to read 4 bytes: socket error or timeout MongoDB\Driver\Exception\ConnectionTimeoutException(%d): Failed to send "delete" command with database "%s": Failed to read 4 bytes: socket error or timeout -object(MongoDB\Driver\WriteResult)#%d (9) { +object(MongoDB\Driver\WriteResult)#%d (%d) { ["nInserted"]=> int(1) ["nMatched"]=> @@ -59,7 +59,10 @@ object(MongoDB\Driver\WriteResult)#%d (9) { ["writeConcernError"]=> NULL ["writeConcern"]=> - object(MongoDB\Driver\WriteConcern)#%d (0) { + object(MongoDB\Driver\WriteConcern)#%d (%d) { + } + ["errorReplies"]=> + array(0) { } } ===DONE=== diff --git a/tests/replicaset/writeresult-getserver-002.phpt b/tests/replicaset/writeresult-getserver-002.phpt index 5ffdc3223..e78b88447 100644 --- a/tests/replicaset/writeresult-getserver-002.phpt +++ b/tests/replicaset/writeresult-getserver-002.phpt @@ -83,6 +83,9 @@ object(MongoDB\Driver\WriteResult)#%d (%d) { ["w"]=> int(1) } + ["errorReplies"]=> + array(0) { + } } string(%d) "%s" int(%d) diff --git a/tests/server/server-executeBulkWrite-001.phpt b/tests/server/server-executeBulkWrite-001.phpt index 3d0a58035..355461635 100644 --- a/tests/server/server-executeBulkWrite-001.phpt +++ b/tests/server/server-executeBulkWrite-001.phpt @@ -73,6 +73,9 @@ object(MongoDB\Driver\WriteResult)#%d (%d) { ["writeConcern"]=> object(MongoDB\Driver\WriteConcern)#%d (%d) { } + ["errorReplies"]=> + array(0) { + } } ===> Collection diff --git a/tests/standalone/writeresult-isacknowledged-001.phpt b/tests/standalone/writeresult-isacknowledged-001.phpt index 0f854782f..f634bae00 100644 --- a/tests/standalone/writeresult-isacknowledged-001.phpt +++ b/tests/standalone/writeresult-isacknowledged-001.phpt @@ -44,5 +44,8 @@ object(MongoDB\Driver\WriteResult)#%d (%d) { ["writeConcern"]=> object(MongoDB\Driver\WriteConcern)#%d (%d) { } + ["errorReplies"]=> + array(0) { + } } ===DONE=== diff --git a/tests/standalone/writeresult-isacknowledged-002.phpt b/tests/standalone/writeresult-isacknowledged-002.phpt index 9c8f3a679..e44d22fda 100644 --- a/tests/standalone/writeresult-isacknowledged-002.phpt +++ b/tests/standalone/writeresult-isacknowledged-002.phpt @@ -49,5 +49,8 @@ object(MongoDB\Driver\WriteResult)#%d (%d) { ["w"]=> int(0) } + ["errorReplies"]=> + array(0) { + } } ===DONE=== diff --git a/tests/standalone/writeresult-isacknowledged-003.phpt b/tests/standalone/writeresult-isacknowledged-003.phpt index 7d0b79204..e30e53312 100644 --- a/tests/standalone/writeresult-isacknowledged-003.phpt +++ b/tests/standalone/writeresult-isacknowledged-003.phpt @@ -46,5 +46,8 @@ object(MongoDB\Driver\WriteResult)#%d (%d) { ["w"]=> int(0) } + ["errorReplies"]=> + array(0) { + } } ===DONE=== diff --git a/tests/writeResult/writeresult-debug-001.phpt b/tests/writeResult/writeresult-debug-001.phpt index af5036e4c..380d14605 100644 --- a/tests/writeResult/writeresult-debug-001.phpt +++ b/tests/writeResult/writeresult-debug-001.phpt @@ -67,5 +67,8 @@ object(MongoDB\Driver\WriteResult)#%d (%d) { ["writeConcern"]=> object(MongoDB\Driver\WriteConcern)#%d (%d) { } + ["errorReplies"]=> + array(0) { + } } ===DONE=== diff --git a/tests/writeResult/writeresult-debug-002.phpt b/tests/writeResult/writeresult-debug-002.phpt index 013e35237..b2e4fce86 100644 --- a/tests/writeResult/writeresult-debug-002.phpt +++ b/tests/writeResult/writeresult-debug-002.phpt @@ -115,5 +115,8 @@ object(MongoDB\Driver\WriteResult)#%d (%d) { ["w"]=> int(30) } + ["errorReplies"]=> + array(0) { + } } ===DONE=== diff --git a/tests/writeResult/writeresult-getErrorReplies-001.phpt b/tests/writeResult/writeresult-getErrorReplies-001.phpt new file mode 100644 index 000000000..ac4f9bb4c --- /dev/null +++ b/tests/writeResult/writeresult-getErrorReplies-001.phpt @@ -0,0 +1,40 @@ +--TEST-- +MongoDB\Driver\WriteResult::getErrorReplies() +--SKIPIF-- + + + + +--FILE-- +selectServer(); + +configureTargetedFailPoint( + $server, + 'failCommand', + ['times' => 1] , + ['errorCode' => 8, 'failCommands' => ['insert']] +); + +$errors = []; +try { + $bulk = new MongoDB\Driver\BulkWrite; + $bulk->insert(['_id' => 1, 'x' => 'bar']); + $server->executeBulkWrite(NS, $bulk); +} catch (MongoDB\Driver\Exception\BulkWriteException $e) { + $errors = $e->getWriteResult()->getErrorReplies(); +} + +var_dump(count($errors)); +var_dump($errors[0]->code); + +?> +===DONE=== + +--EXPECT-- +int(1) +int(8) +===DONE===