@@ -49,6 +49,74 @@ PHONGO_API zend_class_entry *php_phongo_bulkwrite_ce;
49
49
50
50
zend_object_handlers php_phongo_handler_bulkwrite ;
51
51
52
+ /* Returns whether any top-level field names in the document contain a "$". */
53
+ static inline bool php_phongo_bulkwrite_update_has_operators (bson_t * bupdate ) /* {{{ */
54
+ {
55
+ bson_iter_t iter ;
56
+
57
+ if (bson_iter_init (& iter , bupdate )) {
58
+ while (bson_iter_next (& iter )) {
59
+ if (strchr (bson_iter_key (& iter ), '$' )) {
60
+ return true;
61
+ }
62
+ }
63
+ }
64
+
65
+ return false;
66
+ } /* }}} */
67
+
68
+ #define PHONGO_BULKWRITE_APPEND_BOOL (opt , value ) \
69
+ if (!BSON_APPEND_BOOL(boptions, (opt), (value))) { \
70
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT TSRMLS_CC, "Error appending \"%s\" option", (opt)); \
71
+ return false; \
72
+ }
73
+
74
+ #define PHONGO_BULKWRITE_APPEND_INT32 (opt , value ) \
75
+ if (!BSON_APPEND_INT32(boptions, (opt), (value))) { \
76
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT TSRMLS_CC, "Error appending \"%s\" option", (opt)); \
77
+ return false; \
78
+ }
79
+
80
+ /* Applies options (including defaults) for an update operation. */
81
+ static bool php_phongo_bulkwrite_update_apply_options (bson_t * boptions , zval * zoptions TSRMLS_DC )/* {{{ */
82
+ {
83
+ bool multi = false, upsert = false;
84
+
85
+ if (zoptions ) {
86
+ if (php_array_existsc (zoptions , "multi" )) {
87
+ multi = php_array_fetchc_bool (zoptions , "multi" );
88
+ }
89
+ if (php_array_existsc (zoptions , "upsert" )) {
90
+ upsert = php_array_fetchc_bool (zoptions , "upsert" );
91
+ }
92
+ }
93
+
94
+ PHONGO_BULKWRITE_APPEND_BOOL ("multi" , multi );
95
+ PHONGO_BULKWRITE_APPEND_BOOL ("upsert" , upsert );
96
+
97
+ return true;
98
+ } /* }}} */
99
+
100
+ /* Applies options (including defaults) for an delete operation. */
101
+ static bool php_phongo_bulkwrite_delete_apply_options (bson_t * boptions , zval * zoptions TSRMLS_DC )/* {{{ */
102
+ {
103
+ int32_t limit = 0 ;
104
+
105
+ if (zoptions ) {
106
+ if (php_array_existsc (zoptions , "limit" )) {
107
+ limit = php_array_fetchc_bool (zoptions , "limit" ) ? 1 : 0 ;
108
+ }
109
+ }
110
+
111
+ PHONGO_BULKWRITE_APPEND_INT32 ("limit" , limit );
112
+
113
+ return true;
114
+ } /* }}} */
115
+
116
+ #undef PHONGO_BULKWRITE_APPEND_BOOL
117
+ #undef PHONGO_BULKWRITE_APPEND_INT32
118
+ #undef PHONGO_BULKWRITE_OPT_DOCUMENT
119
+
52
120
/* {{{ proto void BulkWrite::__construct([array $options = array()])
53
121
Constructs a new BulkWrite */
54
122
PHP_METHOD (BulkWrite , __construct )
@@ -135,92 +203,100 @@ PHP_METHOD(BulkWrite, insert)
135
203
Adds an update operation to the BulkWrite */
136
204
PHP_METHOD (BulkWrite , update )
137
205
{
138
- php_phongo_bulkwrite_t * intern ;
139
- zval * query ;
140
- zval * newObj ;
141
- zval * updateOptions = NULL ;
142
- mongoc_update_flags_t flags = MONGOC_UPDATE_NONE ;
143
- bson_t * bquery ;
144
- bson_t * bupdate ;
206
+ php_phongo_bulkwrite_t * intern ;
207
+ zval * zquery , * zupdate , * zoptions = NULL ;
208
+ bson_t * bquery , * bupdate , * boptions = NULL ;
209
+ bson_error_t error = {0 };
145
210
SUPPRESS_UNUSED_WARNING (return_value_ptr ) SUPPRESS_UNUSED_WARNING (return_value ) SUPPRESS_UNUSED_WARNING (return_value_used )
146
211
147
212
148
213
intern = Z_BULKWRITE_OBJ_P (getThis ());
149
214
150
- if (zend_parse_parameters (ZEND_NUM_ARGS () TSRMLS_CC , "AA|a!" , & query , & newObj , & updateOptions ) == FAILURE ) {
215
+ if (zend_parse_parameters (ZEND_NUM_ARGS () TSRMLS_CC , "AA|a!" , & zquery , & zupdate , & zoptions ) == FAILURE ) {
151
216
return ;
152
217
}
153
218
154
-
155
219
bquery = bson_new ();
156
220
bupdate = bson_new ();
221
+ boptions = bson_new ();
157
222
158
- phongo_zval_to_bson (query , PHONGO_BSON_NONE , bquery , NULL TSRMLS_CC );
159
- phongo_zval_to_bson (newObj , PHONGO_BSON_NONE , bupdate , NULL TSRMLS_CC );
223
+ phongo_zval_to_bson (zquery , PHONGO_BSON_NONE , bquery , NULL TSRMLS_CC );
160
224
161
- if (updateOptions ) {
162
- flags |= php_array_fetchc_bool (updateOptions , "multi" ) ? MONGOC_UPDATE_MULTI_UPDATE : 0 ;
163
- flags |= php_array_fetchc_bool (updateOptions , "upsert" ) ? MONGOC_UPDATE_UPSERT : 0 ;
225
+ if (EG (exception )) {
226
+ goto cleanup ;
164
227
}
165
228
166
- if (flags & MONGOC_UPDATE_MULTI_UPDATE ) {
167
- mongoc_bulk_operation_update (intern -> bulk , bquery , bupdate , !!(flags & MONGOC_UPDATE_UPSERT ));
168
- } else {
169
- bson_iter_t iter ;
170
- zend_bool replaced = 0 ;
171
-
172
- if (bson_iter_init (& iter , bupdate )) {
173
- while (bson_iter_next (& iter )) {
174
- if (!strchr (bson_iter_key (& iter ), '$' )) {
175
- mongoc_bulk_operation_replace_one (intern -> bulk , bquery , bupdate , !!(flags & MONGOC_UPDATE_UPSERT ));
176
- replaced = 1 ;
177
- break ;
178
- }
179
- }
180
- }
229
+ phongo_zval_to_bson (zupdate , PHONGO_BSON_NONE , bupdate , NULL TSRMLS_CC );
230
+
231
+ if (EG (exception )) {
232
+ goto cleanup ;
233
+ }
234
+
235
+ if (!php_phongo_bulkwrite_update_apply_options (boptions , zoptions TSRMLS_CC )) {
236
+ goto cleanup ;
237
+ }
181
238
182
- if (!replaced ) {
183
- mongoc_bulk_operation_update_one (intern -> bulk , bquery , bupdate , !!(flags & MONGOC_UPDATE_UPSERT ));
239
+ if (php_phongo_bulkwrite_update_has_operators (bupdate )) {
240
+ if (!mongoc_bulk_operation_update_with_opts (intern -> bulk , bquery , bupdate , boptions , & error )) {
241
+ phongo_throw_exception_from_bson_error_t (& error TSRMLS_CC );
242
+ goto cleanup ;
243
+ }
244
+ } else {
245
+ if (!mongoc_bulk_operation_replace_one_with_opts (intern -> bulk , bquery , bupdate , boptions , & error )) {
246
+ phongo_throw_exception_from_bson_error_t (& error TSRMLS_CC );
247
+ goto cleanup ;
184
248
}
185
249
}
186
250
187
251
intern -> num_ops ++ ;
188
252
253
+ cleanup :
189
254
bson_clear (& bquery );
190
255
bson_clear (& bupdate );
256
+ bson_clear (& boptions );
191
257
}
192
258
/* }}} */
193
259
194
260
/* {{{ proto void BulkWrite::delete(array|object $query[, array $deleteOptions = array()])
195
261
Adds a delete operation to the BulkWrite */
196
262
PHP_METHOD (BulkWrite , delete )
197
263
{
198
- php_phongo_bulkwrite_t * intern ;
199
- zval * query ;
200
- zval * deleteOptions = NULL ;
201
- bson_t * bson ;
264
+ php_phongo_bulkwrite_t * intern ;
265
+ zval * zquery , * zoptions = NULL ;
266
+ bson_t * bquery , * boptions = NULL ;
267
+ bson_error_t error = { 0 } ;
202
268
SUPPRESS_UNUSED_WARNING (return_value_ptr ) SUPPRESS_UNUSED_WARNING (return_value ) SUPPRESS_UNUSED_WARNING (return_value_used )
203
269
204
270
205
271
intern = Z_BULKWRITE_OBJ_P (getThis ());
206
272
207
- if (zend_parse_parameters (ZEND_NUM_ARGS () TSRMLS_CC , "A|a!" , & query , & deleteOptions ) == FAILURE ) {
273
+ if (zend_parse_parameters (ZEND_NUM_ARGS () TSRMLS_CC , "A|a!" , & zquery , & zoptions ) == FAILURE ) {
208
274
return ;
209
275
}
210
276
277
+ bquery = bson_new ();
278
+ boptions = bson_new ();
211
279
212
- bson = bson_new ();
213
- phongo_zval_to_bson (query , PHONGO_BSON_NONE , bson , NULL TSRMLS_CC );
280
+ phongo_zval_to_bson (zquery , PHONGO_BSON_NONE , bquery , NULL TSRMLS_CC );
214
281
215
- if (deleteOptions && php_array_fetchc_bool (deleteOptions , "limit" )) {
216
- mongoc_bulk_operation_remove_one (intern -> bulk , bson );
217
- } else {
218
- mongoc_bulk_operation_remove (intern -> bulk , bson );
282
+ if (EG (exception )) {
283
+ goto cleanup ;
284
+ }
285
+
286
+ if (!php_phongo_bulkwrite_delete_apply_options (boptions , zoptions TSRMLS_CC )) {
287
+ goto cleanup ;
288
+ }
289
+
290
+ if (!mongoc_bulk_operation_remove_with_opts (intern -> bulk , bquery , boptions , & error )) {
291
+ phongo_throw_exception_from_bson_error_t (& error TSRMLS_CC );
292
+ goto cleanup ;
219
293
}
220
294
221
295
intern -> num_ops ++ ;
222
296
223
- bson_clear (& bson );
297
+ cleanup :
298
+ bson_clear (& bquery );
299
+ bson_clear (& boptions );
224
300
}
225
301
/* }}} */
226
302
0 commit comments