Skip to content

Commit 7cd2a1b

Browse files
committed
PHPC-1462: Support hint for update commands
1 parent d93d1b7 commit 7cd2a1b

File tree

4 files changed

+122
-0
lines changed

4 files changed

+122
-0
lines changed

src/MongoDB/BulkWrite.c

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,36 @@ static bool php_phongo_bulkwrite_opts_append_document(bson_t* opts, const char*
237237
} \
238238
}
239239

240+
/* Initialize the "hint" option. Returns true on success; otherwise, false is
241+
* returned and an exception is thrown.
242+
*
243+
* The "hint" option must be a string or document. Check for both types and
244+
* merge into BSON options accordingly. */
245+
static bool php_phongo_bulkwrite_opt_hint(bson_t* boptions, zval* zoptions TSRMLS_DC) /* {{{ */
246+
{
247+
/* The "hint" option (or "$hint" modifier) must be a string or document.
248+
* Check for both types and merge into BSON options accordingly. */
249+
if (zoptions && php_array_existsc(zoptions, "hint")) {
250+
zend_uchar type = Z_TYPE_P(php_array_fetchc(zoptions, "hint"));
251+
252+
if (type == IS_STRING) {
253+
zval* value = php_array_fetchc(zoptions, "hint");
254+
255+
if (!bson_append_utf8(boptions, "hint", 4, Z_STRVAL_P(value), Z_STRLEN_P(value))) {
256+
phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT TSRMLS_CC, "Error appending \"hint\" option");
257+
return false;
258+
}
259+
} else if (type == IS_OBJECT || type == IS_ARRAY) {
260+
PHONGO_BULKWRITE_OPT_DOCUMENT("hint");
261+
} else {
262+
phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT TSRMLS_CC, "Expected \"hint\" option to be string, array, or object, %s given", zend_get_type_by_const(type));
263+
return false;
264+
}
265+
}
266+
267+
return true;
268+
} /* }}} */
269+
240270
/* Applies options (including defaults) for an update operation. */
241271
static bool php_phongo_bulkwrite_update_apply_options(bson_t* boptions, zval* zoptions TSRMLS_DC) /* {{{ */
242272
{
@@ -252,6 +282,10 @@ static bool php_phongo_bulkwrite_update_apply_options(bson_t* boptions, zval* zo
252282
PHONGO_BULKWRITE_OPT_ARRAY("arrayFilters");
253283
PHONGO_BULKWRITE_OPT_DOCUMENT("collation");
254284

285+
if (!php_phongo_bulkwrite_opt_hint(boptions, zoptions TSRMLS_CC)) {
286+
return false;
287+
}
288+
255289
return true;
256290
} /* }}} */
257291

tests/bulk/bulkwrite-update-004.phpt

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
--TEST--
2+
MongoDB\Driver\BulkWrite::update() with hint option
3+
--SKIPIF--
4+
<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
5+
<?php skip_if_not_live(); ?>
6+
<?php skip_if_server_version('<', '4.2'); ?>
7+
<?php skip_if_not_clean(); ?>
8+
--FILE--
9+
<?php
10+
require_once __DIR__ . "/../utils/basic.inc";
11+
12+
class CommandLogger implements MongoDB\Driver\Monitoring\CommandSubscriber
13+
{
14+
public function commandStarted(MongoDB\Driver\Monitoring\CommandStartedEvent $event)
15+
{
16+
if ($event->getCommandName() !== 'update') {
17+
return;
18+
}
19+
20+
printf("update included hint: %s\n", json_encode($event->getCommand()->updates[0]->hint));
21+
}
22+
23+
public function commandSucceeded(MongoDB\Driver\Monitoring\CommandSucceededEvent $event)
24+
{
25+
}
26+
27+
public function commandFailed(MongoDB\Driver\Monitoring\CommandFailedEvent $event)
28+
{
29+
}
30+
}
31+
32+
$manager = new MongoDB\Driver\Manager(URI);
33+
34+
$bulk = new MongoDB\Driver\BulkWrite();
35+
$bulk->insert(['x' => 1]);
36+
$bulk->insert(['x' => 2]);
37+
$manager->executeBulkWrite(NS, $bulk);
38+
39+
MongoDB\Driver\Monitoring\addSubscriber(new CommandLogger);
40+
41+
$bulk = new MongoDB\Driver\BulkWrite;
42+
$bulk->update(['_id' => 1], ['$set' => ['x' => 11]], ['hint' => '_id_']);
43+
$manager->executeBulkWrite(NS, $bulk);
44+
45+
$bulk = new MongoDB\Driver\BulkWrite;
46+
$bulk->update(['_id' => 2], ['$set' => ['x' => 22]], ['hint' => ['_id' => 1]]);
47+
$manager->executeBulkWrite(NS, $bulk);
48+
49+
?>
50+
===DONE===
51+
<?php exit(0); ?>
52+
--EXPECTF--
53+
update included hint: "_id_"
54+
update included hint: {"_id":1}
55+
===DONE===

tests/bulk/bulkwrite-update_error-003.phpt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,10 @@ echo throws(function() use ($bulk) {
2525

2626
echo throws(function() use ($bulk) {
2727
$bulk->update(['x' => 1], ['$set' => ['y' => 1]], ['arrayFilters' => ['foo' => 'bar']]);
28+
}, 'MongoDB\Driver\Exception\InvalidArgumentException'), "\n\n";
29+
30+
echo throws(function() use ($bulk) {
31+
$bulk->update(['x' => 1], ['$set' => ['y' => 1]], ['hint' => 1]);
2832
}, 'MongoDB\Driver\Exception\InvalidArgumentException'), "\n";
2933

3034
?>
@@ -45,4 +49,7 @@ Expected "arrayFilters" option to be array or object, int%S given
4549

4650
OK: Got MongoDB\Driver\Exception\InvalidArgumentException
4751
"arrayFilters" option has invalid keys for a BSON array
52+
53+
OK: Got MongoDB\Driver\Exception\InvalidArgumentException
54+
Expected "hint" option to be string, array, or object, int%S given
4855
===DONE===
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
--TEST--
2+
MongoDB\Driver\BulkWrite::update() hint option requires MongoDB 4.2
3+
--SKIPIF--
4+
<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
5+
<?php skip_if_not_live(); ?>
6+
<?php skip_if_server_version('>=', '4.2'); ?>
7+
--FILE--
8+
<?php
9+
require_once __DIR__ . "/../utils/basic.inc";
10+
11+
$manager = new MongoDB\Driver\Manager(URI);
12+
13+
$bulk = new MongoDB\Driver\BulkWrite;
14+
$bulk->update(['_id' => 1], ['$set' => ['x' => 11]], ['hint' => '_id_']);
15+
16+
echo throws(function() use ($manager, $bulk) {
17+
$manager->executeBulkWrite(NS, $bulk);
18+
}, 'MongoDB\Driver\Exception\BulkWriteException'), "\n";
19+
20+
?>
21+
===DONE===
22+
<?php exit(0); ?>
23+
--EXPECT--
24+
OK: Got MongoDB\Driver\Exception\BulkWriteException
25+
Bulk write failed due to previous MongoDB\Driver\Exception\RuntimeException: The selected server does not support hint for update
26+
===DONE===

0 commit comments

Comments
 (0)