Skip to content

Commit

Permalink
Merge pull request #83 from arieltorti/master
Browse files Browse the repository at this point in the history
Allow "$regex" inside "$not" queries on Mongo 4
  • Loading branch information
davidlatwe authored Jul 21, 2023
2 parents bf16d65 + 6745c7e commit 4653538
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 2 deletions.
3 changes: 3 additions & 0 deletions montydb/configure.py
Original file line number Diff line number Diff line change
Expand Up @@ -310,13 +310,16 @@ def patch(mod, func, ver_func):
patch(queries, "_is_comparable", "_is_comparable_ver4")
patch(queries, "_regex_options_check", "_regex_options_")
patch(queries, "_mod_remainder_not_num", "_mod_remainder_not_num_")
patch(queries, "_not_subspec_op_check", "_not_validate_subspec_op_v4")

elif version == "4.2":
patch(queries, "_is_comparable", "_is_comparable_ver4")
patch(queries, "_regex_options_check", "_regex_options_v42")
patch(queries, "_mod_remainder_not_num", "_mod_remainder_not_num_v42")
patch(queries, "_not_subspec_op_check", "_not_validate_subspec_op_v4")

else:
patch(queries, "_is_comparable", "_is_comparable_ver4")
patch(queries, "_regex_options_check", "_regex_options_")
patch(queries, "_mod_remainder_not_num", "_mod_remainder_not_num_v42")
patch(queries, "_not_subspec_op_check", "_not_validate_subspec_op_v4")
15 changes: 13 additions & 2 deletions montydb/engine/queries.py
Original file line number Diff line number Diff line change
Expand Up @@ -377,8 +377,7 @@ def _parse_not(self, sub_spec):
for op in sub_spec:
if op not in self.field_ops:
raise OperationFailure("unknown operator: {}".format(op))
if op == "$regex":
raise OperationFailure("$not cannot have a regex")
_not_subspec_op_check(op)

return self.subparser("$not", sub_spec)

Expand All @@ -403,6 +402,18 @@ def _is_expression_obj(sub_spec):
return is_duckument_type(sub_spec) and next(iter(sub_spec)).startswith("$")


def _not_validate_subspec_op_(op):
if op == "$regex":
raise OperationFailure("$not cannot have a regex")


def _not_validate_subspec_op_v4(sub_spec):
pass


_not_subspec_op_check = _not_validate_subspec_op_


# Only for preserving `int` type flags to bypass
# internal "flags must be string" type check
class _FALG(object):
Expand Down
27 changes: 27 additions & 0 deletions tests/test_engine/test_queries/test_queryop_logical_not.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@

import re
import pytest
from montydb.types import bson

from pymongo.errors import OperationFailure as MongoOpFail
from montydb.errors import OperationFailure as MontyOpFail

from ...conftest import skip_if_no_bson


Expand Down Expand Up @@ -76,3 +81,25 @@ def test_qop_not_5(monty_find, mongo_find):
assert count_documents(mongo_c, spec) == 1
assert count_documents(monty_c, spec) == count_documents(mongo_c, spec)
assert next(monty_c) == next(mongo_c)


def test_qop_not_6(monty_find, mongo_find, mongo_version):
docs = [
{"a": "apple"},
{"a": "banana"},
]
spec = {"a": {"$not": {"$regex": "^a"}}}

monty_c = monty_find(docs, spec)
mongo_c = mongo_find(docs, spec)

if mongo_version[0] == 3:
with pytest.raises(MongoOpFail):
next(mongo_c)
with pytest.raises(MontyOpFail):
next(monty_c)
return

assert count_documents(mongo_c, spec) == 1
assert count_documents(monty_c, spec) == count_documents(mongo_c, spec)
assert next(monty_c) == next(mongo_c)

0 comments on commit 4653538

Please sign in to comment.