Skip to content

Commit f26f78e

Browse files
committed
Merge pull request #842
2 parents e398717 + 3c8fdfd commit f26f78e

File tree

6 files changed

+109
-36
lines changed

6 files changed

+109
-36
lines changed

src/MongoDB/BulkWrite.c

Lines changed: 82 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -73,15 +73,79 @@ static inline bool php_phongo_bulkwrite_update_has_operators(bson_t* bupdate) /*
7373
return false;
7474
} /* }}} */
7575

76+
/* Returns whether the BSON array's keys are a sequence of integer strings
77+
* starting with "0". BSON_APPEND_ARRAY considers it the caller's responsibility
78+
* to ensure that the array's keys are properly formatted. */
79+
static inline bool php_phongo_bulkwrite_bson_array_has_valid_keys(bson_t* array) /* {{{ */
80+
{
81+
bson_iter_t iter;
82+
83+
if (bson_empty(array)) {
84+
return true;
85+
}
86+
87+
if (bson_iter_init(&iter, array)) {
88+
char key[12];
89+
int count = 0;
90+
91+
while (bson_iter_next(&iter)) {
92+
bson_snprintf(key, sizeof(key), "%d", count);
93+
94+
if (0 != strcmp(key, bson_iter_key(&iter))) {
95+
return false;
96+
}
97+
98+
count++;
99+
}
100+
}
101+
102+
return true;
103+
} /* }}} */
104+
105+
/* Appends an array field for the given opts document and key. Returns true on
106+
* success; otherwise, false is returned and an exception is thrown. */
107+
static bool php_phongo_bulkwrite_opts_append_array(bson_t* opts, const char* key, zval* zarr TSRMLS_DC) /* {{{ */
108+
{
109+
zval* value = php_array_fetch(zarr, key);
110+
bson_t b = BSON_INITIALIZER;
111+
112+
if (Z_TYPE_P(value) != IS_OBJECT && Z_TYPE_P(value) != IS_ARRAY) {
113+
phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT TSRMLS_CC, "Expected \"%s\" option to be array or object, %s given", key, zend_get_type_by_const(Z_TYPE_P(value)));
114+
return false;
115+
}
116+
117+
php_phongo_zval_to_bson(value, PHONGO_BSON_NONE, &b, NULL TSRMLS_CC);
118+
119+
if (EG(exception)) {
120+
bson_destroy(&b);
121+
return false;
122+
}
123+
124+
if (!php_phongo_bulkwrite_bson_array_has_valid_keys(&b)) {
125+
phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT TSRMLS_CC, "\"%s\" option has invalid keys for a BSON array", key);
126+
bson_destroy(&b);
127+
return false;
128+
}
129+
130+
if (!BSON_APPEND_ARRAY(opts, key, &b)) {
131+
phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT TSRMLS_CC, "Error appending \"%s\" option", key);
132+
bson_destroy(&b);
133+
return false;
134+
}
135+
136+
bson_destroy(&b);
137+
return true;
138+
} /* }}} */
139+
76140
/* Appends a document field for the given opts document and key. Returns true on
77141
* success; otherwise, false is returned and an exception is thrown. */
78-
static bool php_phongo_bulkwrite_opts_append_document(bson_t* opts, const char* opts_key, zval* zarr, const char* zarr_key TSRMLS_DC) /* {{{ */
142+
static bool php_phongo_bulkwrite_opts_append_document(bson_t* opts, const char* key, zval* zarr TSRMLS_DC) /* {{{ */
79143
{
80-
zval* value = php_array_fetch(zarr, zarr_key);
144+
zval* value = php_array_fetch(zarr, key);
81145
bson_t b = BSON_INITIALIZER;
82146

83147
if (Z_TYPE_P(value) != IS_OBJECT && Z_TYPE_P(value) != IS_ARRAY) {
84-
phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT TSRMLS_CC, "Expected \"%s\" option to be array or object, %s given", zarr_key, zend_get_type_by_const(Z_TYPE_P(value)));
148+
phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT TSRMLS_CC, "Expected \"%s\" option to be array or object, %s given", key, zend_get_type_by_const(Z_TYPE_P(value)));
85149
return false;
86150
}
87151

@@ -92,8 +156,8 @@ static bool php_phongo_bulkwrite_opts_append_document(bson_t* opts, const char*
92156
return false;
93157
}
94158

95-
if (!BSON_APPEND_DOCUMENT(opts, opts_key, &b)) {
96-
phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT TSRMLS_CC, "Error appending \"%s\" option", opts_key);
159+
if (!BSON_APPEND_DOCUMENT(opts, key, &b)) {
160+
phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT TSRMLS_CC, "Error appending \"%s\" option", key);
97161
bson_destroy(&b);
98162
return false;
99163
}
@@ -114,11 +178,18 @@ static bool php_phongo_bulkwrite_opts_append_document(bson_t* opts, const char*
114178
return false; \
115179
}
116180

117-
#define PHONGO_BULKWRITE_OPT_DOCUMENT(opt) \
118-
if (zoptions && php_array_existsc(zoptions, (opt))) { \
119-
if (!php_phongo_bulkwrite_opts_append_document(boptions, (opt), zoptions, (opt) TSRMLS_CC)) { \
120-
return false; \
121-
} \
181+
#define PHONGO_BULKWRITE_OPT_ARRAY(opt) \
182+
if (zoptions && php_array_existsc(zoptions, (opt))) { \
183+
if (!php_phongo_bulkwrite_opts_append_array(boptions, (opt), zoptions TSRMLS_CC)) { \
184+
return false; \
185+
} \
186+
}
187+
188+
#define PHONGO_BULKWRITE_OPT_DOCUMENT(opt) \
189+
if (zoptions && php_array_existsc(zoptions, (opt))) { \
190+
if (!php_phongo_bulkwrite_opts_append_document(boptions, (opt), zoptions TSRMLS_CC)) { \
191+
return false; \
192+
} \
122193
}
123194

124195
/* Applies options (including defaults) for an update operation. */
@@ -137,7 +208,7 @@ static bool php_phongo_bulkwrite_update_apply_options(bson_t* boptions, zval* zo
137208

138209
PHONGO_BULKWRITE_APPEND_BOOL("multi", multi);
139210
PHONGO_BULKWRITE_APPEND_BOOL("upsert", upsert);
140-
PHONGO_BULKWRITE_OPT_DOCUMENT("arrayFilters");
211+
PHONGO_BULKWRITE_OPT_ARRAY("arrayFilters");
141212
PHONGO_BULKWRITE_OPT_DOCUMENT("collation");
142213

143214
return true;

tests/bulk/bulkwrite-update-arrayFilters-001.phpt

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
--TEST--
22
MongoDB\Driver\BulkWrite::update with arrayFilters
3-
--XFAIL--
4-
START() tests must be reimplemented (PHPC-1179)
53
--SKIPIF--
64
<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
7-
<?php START('THROWAWAY', ["version" => "36-release"]); CLEANUP(THROWAWAY); ?>
5+
<?php skip_if_not_live(); ?>
6+
<?php skip_if_server_version('<', '3.6'); ?>
7+
<?php skip_if_not_clean(); ?>
88
--FILE--
99
<?php
1010
require_once __DIR__ . "/../utils/basic.inc";
1111

12-
$manager = new MongoDB\Driver\Manager(THROWAWAY);
12+
$manager = new MongoDB\Driver\Manager(URI);
1313

1414
$bulk = new MongoDB\Driver\BulkWrite();
1515

@@ -35,11 +35,7 @@ $cursor = $manager->executeQuery( DATABASE_NAME . '.' . COLLECTION_NAME, new \Mo
3535
var_dump($cursor->toArray());
3636
?>
3737
===DONE===
38-
<?php DELETE("THROWAWAY"); ?>
3938
<?php exit(0); ?>
40-
--CLEAN--
41-
<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
42-
<?php DELETE("THROWAWAY"); ?>
4339
--EXPECTF--
4440
array(%d) {
4541
[0]=>

tests/bulk/bulkwrite-update_error-003.phpt

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,14 @@ echo throws(function() use ($bulk) {
1717

1818
echo throws(function() use ($bulk) {
1919
$bulk->update(['x' => 1], ['$set' => ['y' => 1]], ['collation' => 1]);
20+
}, 'MongoDB\Driver\Exception\InvalidArgumentException'), "\n\n";
21+
22+
echo throws(function() use ($bulk) {
23+
$bulk->update(['x' => 1], ['$set' => ['y' => 1]], ['arrayFilters' => 1]);
24+
}, 'MongoDB\Driver\Exception\InvalidArgumentException'), "\n\n";
25+
26+
echo throws(function() use ($bulk) {
27+
$bulk->update(['x' => 1], ['$set' => ['y' => 1]], ['arrayFilters' => ['foo' => 'bar']]);
2028
}, 'MongoDB\Driver\Exception\InvalidArgumentException'), "\n";
2129

2230
?>
@@ -31,4 +39,10 @@ Expected "collation" option to be array or object, int%S given
3139

3240
OK: Got MongoDB\Driver\Exception\InvalidArgumentException
3341
Expected "collation" option to be array or object, int%S given
42+
43+
OK: Got MongoDB\Driver\Exception\InvalidArgumentException
44+
Expected "arrayFilters" option to be array or object, int%S given
45+
46+
OK: Got MongoDB\Driver\Exception\InvalidArgumentException
47+
"arrayFilters" option has invalid keys for a BSON array
3448
===DONE===

tests/command/findAndModify-001.phpt

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
--TEST--
22
MongoDB\Driver\Command with findAndModify and arrayFilters
3-
--XFAIL--
4-
START() tests must be reimplemented (PHPC-1179)
53
--SKIPIF--
64
<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
7-
<?php START('THROWAWAY', ["version" => "36-release"]); CLEANUP(THROWAWAY); ?>
5+
<?php skip_if_not_live(); ?>
6+
<?php skip_if_server_version('<', '3.6'); ?>
7+
<?php skip_if_not_clean(); ?>
88
--FILE--
99
<?php
1010
require_once __DIR__ . "/../utils/basic.inc";
1111

12-
$manager = new MongoDB\Driver\Manager(THROWAWAY);
12+
$manager = new MongoDB\Driver\Manager(URI);
1313

1414
$bulk = new MongoDB\Driver\BulkWrite();
1515

@@ -35,11 +35,7 @@ $cursor = $manager->executeQuery( DATABASE_NAME . '.' . COLLECTION_NAME, new \Mo
3535
var_dump($cursor->toArray());
3636
?>
3737
===DONE===
38-
<?php DELETE("THROWAWAY"); ?>
3938
<?php exit(0); ?>
40-
--CLEAN--
41-
<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
42-
<?php DELETE("THROWAWAY"); ?>
4339
--EXPECTF--
4440
array(%d) {
4541
[0]=>

tests/command/update-001.phpt

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
--TEST--
22
MongoDB\Driver\Command with update and arrayFilters
3-
--XFAIL--
4-
START() tests must be reimplemented (PHPC-1179)
53
--SKIPIF--
64
<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
7-
<?php START('THROWAWAY', ["version" => "36-release"]); CLEANUP(THROWAWAY); ?>
5+
<?php skip_if_not_live(); ?>
6+
<?php skip_if_server_version('<', '3.6'); ?>
7+
<?php skip_if_not_clean(); ?>
88
--FILE--
99
<?php
1010
require_once __DIR__ . "/../utils/basic.inc";
1111

12-
$manager = new MongoDB\Driver\Manager(THROWAWAY);
12+
$manager = new MongoDB\Driver\Manager(URI);
1313

1414
$bulk = new MongoDB\Driver\BulkWrite();
1515

@@ -35,11 +35,7 @@ $cursor = $manager->executeQuery( DATABASE_NAME . '.' . COLLECTION_NAME, new \Mo
3535
var_dump($cursor->toArray());
3636
?>
3737
===DONE===
38-
<?php DELETE("THROWAWAY"); ?>
3938
<?php exit(0); ?>
40-
--CLEAN--
41-
<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
42-
<?php DELETE("THROWAWAY"); ?>
4339
--EXPECTF--
4440
array(%d) {
4541
[0]=>

0 commit comments

Comments
 (0)