Skip to content

Commit 971af90

Browse files
committed
CDRIVER-1692 allow $-ops inside filter/projection
1 parent 99a0237 commit 971af90

File tree

2 files changed

+59
-12
lines changed

2 files changed

+59
-12
lines changed

src/mongoc/mongoc-cursor.c

Lines changed: 42 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -181,27 +181,51 @@ _mongoc_set_cursor_ns (mongoc_cursor_t *cursor,
181181
}
182182

183183

184-
/* true if there are $ and non-$ keys. precondition: bson must be valid. */
184+
/* true if there are $-keys. precondition: bson must be valid. */
185185
static bool
186-
_mixed_dollar_non_dollar (const bson_t *bson)
186+
_has_dollar_fields (const bson_t *bson)
187187
{
188188
bson_iter_t iter;
189-
bool has_dollar = false;
190-
bool has_non_dollar = false;
191189
const char *key;
192190

193191
BSON_ASSERT (bson_iter_init (&iter, bson));
194192
while (bson_iter_next (&iter)) {
195193
key = bson_iter_key (&iter);
196194

197195
if (key[0] == '$') {
198-
has_dollar = true;
199-
} else {
200-
has_non_dollar = true;
196+
return true;
201197
}
202198
}
203199

204-
return has_dollar && has_non_dollar;
200+
return false;
201+
}
202+
203+
204+
/* true if there are any non-$ keys. precondition: bson must be valid. */
205+
static bool
206+
_has_nondollar_fields (const bson_t *bson)
207+
{
208+
bson_iter_t iter;
209+
const char *key;
210+
211+
BSON_ASSERT (bson_iter_init (&iter, bson));
212+
while (bson_iter_next (&iter)) {
213+
key = bson_iter_key (&iter);
214+
215+
if (key[0] != '$') {
216+
return true;
217+
}
218+
}
219+
220+
return false;
221+
}
222+
223+
224+
/* true if there are $ and non-$ keys. precondition: bson must be valid. */
225+
static bool
226+
_mixed_dollar_non_dollar (const bson_t *bson)
227+
{
228+
return _has_dollar_fields (bson) && _has_nondollar_fields (bson);
205229
}
206230

207231

@@ -248,13 +272,19 @@ _mongoc_cursor_new_with_opts (mongoc_client_t *client,
248272
}
249273

250274
if (opts) {
251-
if (!bson_validate (opts,
252-
BSON_VALIDATE_DOLLAR_KEYS | BSON_VALIDATE_EMPTY_KEYS,
253-
NULL)) {
275+
if (!bson_validate (opts, BSON_VALIDATE_EMPTY_KEYS, NULL)) {
276+
MARK_FAILED (cursor);
277+
bson_set_error (&cursor->error, MONGOC_ERROR_CURSOR,
278+
MONGOC_ERROR_CURSOR_INVALID_CURSOR,
279+
"Cannot use empty keys in 'opts'.");
280+
GOTO (finish);
281+
}
282+
283+
if (_has_dollar_fields (opts)) {
254284
MARK_FAILED (cursor);
255285
bson_set_error (&cursor->error, MONGOC_ERROR_CURSOR,
256286
MONGOC_ERROR_CURSOR_INVALID_CURSOR,
257-
"Cannot use $-modifiers or empty keys in 'opts'.");
287+
"Cannot use $-modifiers in 'opts'.");
258288
GOTO (finish);
259289
}
260290

tests/test-mongoc-collection-find-with-opts.c

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,21 @@ test_fields (void)
303303
}
304304

305305

306+
static void
307+
test_slice (void)
308+
{
309+
test_collection_find_with_opts_t test_data = { 0 };
310+
311+
test_data.opts = "{'projection': {'array': {'$slice': 10}}}";
312+
test_data.expected_op_query_projection = "{'array': {'$slice': 10}}";
313+
test_data.expected_find_command =
314+
"{'find': 'collection', "
315+
" 'filter': {},"
316+
" 'projection': {'array': {'$slice': 10}}}";
317+
_test_collection_find_with_opts (&test_data);
318+
}
319+
320+
306321
static void
307322
test_int_modifiers (void)
308323
{
@@ -731,6 +746,8 @@ test_collection_find_with_opts_install (TestSuite *suite)
731746
test_sort);
732747
TestSuite_Add (suite, "/Collection/find_with_opts/fields",
733748
test_fields);
749+
TestSuite_Add (suite, "/Collection/find_with_opts/slice",
750+
test_slice);
734751
TestSuite_Add (suite, "/Collection/find_with_opts/modifiers/integer",
735752
test_int_modifiers);
736753
TestSuite_Add (suite, "/Collection/find_with_opts/modifiers/index_spec",

0 commit comments

Comments
 (0)