|
20 | 20 | from .features import DatabaseFeatures |
21 | 21 | from .introspection import DatabaseIntrospection |
22 | 22 | from .operations import DatabaseOperations |
23 | | -from .query_utils import regex_match |
24 | 23 | from .schema import DatabaseSchemaEditor |
25 | 24 | from .utils import OperationDebugWrapper |
26 | 25 | from .validation import DatabaseValidation |
@@ -97,44 +96,51 @@ class DatabaseWrapper(BaseDatabaseWrapper): |
97 | 96 | } |
98 | 97 | _connection_pools = {} |
99 | 98 |
|
100 | | - def _isnull_operator(a, b): |
101 | | - is_null = { |
| 99 | + def _isnull_expr(field, is_null): |
| 100 | + mql = { |
102 | 101 | "$or": [ |
103 | 102 | # The path does not exist (i.e. is "missing") |
104 | | - {"$eq": [{"$type": a}, "missing"]}, |
| 103 | + {"$eq": [{"$type": field}, "missing"]}, |
105 | 104 | # or the value is None. |
106 | | - {"$eq": [a, None]}, |
| 105 | + {"$eq": [field, None]}, |
107 | 106 | ] |
108 | 107 | } |
109 | | - return is_null if b else {"$not": is_null} |
| 108 | + return mql if is_null else {"$not": mql} |
| 109 | + |
| 110 | + def _regex_expr(field, regex_vals, insensitive=False): |
| 111 | + regex = {"$concat": regex_vals} if isinstance(regex_vals, tuple) else regex_vals |
| 112 | + options = "i" if insensitive else "" |
| 113 | + return {"$regexMatch": {"input": field, "regex": regex, "options": options}} |
110 | 114 |
|
111 | 115 | mongo_operators = { |
112 | 116 | "exact": lambda a, b: {"$eq": [a, b]}, |
113 | 117 | "gt": lambda a, b: {"$gt": [a, b]}, |
114 | 118 | "gte": lambda a, b: {"$gte": [a, b]}, |
115 | 119 | # MongoDB considers null less than zero. Exclude null values to match |
116 | 120 | # SQL behavior. |
117 | | - "lt": lambda a, b: {"$and": [{"$lt": [a, b]}, DatabaseWrapper._isnull_operator(a, False)]}, |
118 | | - "lte": lambda a, b: { |
119 | | - "$and": [{"$lte": [a, b]}, DatabaseWrapper._isnull_operator(a, False)] |
120 | | - }, |
| 121 | + "lt": lambda a, b: {"$and": [{"$lt": [a, b]}, DatabaseWrapper._isnull_expr(a, False)]}, |
| 122 | + "lte": lambda a, b: {"$and": [{"$lte": [a, b]}, DatabaseWrapper._isnull_expr(a, False)]}, |
121 | 123 | "in": lambda a, b: {"$in": [a, b]}, |
122 | | - "isnull": _isnull_operator, |
| 124 | + "isnull": _isnull_expr, |
123 | 125 | "range": lambda a, b: { |
124 | 126 | "$and": [ |
125 | | - {"$or": [DatabaseWrapper._isnull_operator(b[0], True), {"$gte": [a, b[0]]}]}, |
126 | | - {"$or": [DatabaseWrapper._isnull_operator(b[1], True), {"$lte": [a, b[1]]}]}, |
| 127 | + {"$or": [DatabaseWrapper._isnull_expr(b[0], True), {"$gte": [a, b[0]]}]}, |
| 128 | + {"$or": [DatabaseWrapper._isnull_expr(b[1], True), {"$lte": [a, b[1]]}]}, |
127 | 129 | ] |
128 | 130 | }, |
129 | | - "iexact": lambda a, b: regex_match(a, ("^", b, {"$literal": "$"}), insensitive=True), |
130 | | - "startswith": lambda a, b: regex_match(a, ("^", b)), |
131 | | - "istartswith": lambda a, b: regex_match(a, ("^", b), insensitive=True), |
132 | | - "endswith": lambda a, b: regex_match(a, (b, {"$literal": "$"})), |
133 | | - "iendswith": lambda a, b: regex_match(a, (b, {"$literal": "$"}), insensitive=True), |
134 | | - "contains": lambda a, b: regex_match(a, b), |
135 | | - "icontains": lambda a, b: regex_match(a, b, insensitive=True), |
136 | | - "regex": lambda a, b: regex_match(a, b), |
137 | | - "iregex": lambda a, b: regex_match(a, b, insensitive=True), |
| 131 | + "iexact": lambda a, b: DatabaseWrapper._regex_expr( |
| 132 | + a, ("^", b, {"$literal": "$"}), insensitive=True |
| 133 | + ), |
| 134 | + "startswith": lambda a, b: DatabaseWrapper._regex_expr(a, ("^", b)), |
| 135 | + "istartswith": lambda a, b: DatabaseWrapper._regex_expr(a, ("^", b), insensitive=True), |
| 136 | + "endswith": lambda a, b: DatabaseWrapper._regex_expr(a, (b, {"$literal": "$"})), |
| 137 | + "iendswith": lambda a, b: DatabaseWrapper._regex_expr( |
| 138 | + a, (b, {"$literal": "$"}), insensitive=True |
| 139 | + ), |
| 140 | + "contains": lambda a, b: DatabaseWrapper._regex_expr(a, b), |
| 141 | + "icontains": lambda a, b: DatabaseWrapper._regex_expr(a, b, insensitive=True), |
| 142 | + "regex": lambda a, b: DatabaseWrapper._regex_expr(a, b), |
| 143 | + "iregex": lambda a, b: DatabaseWrapper._regex_expr(a, b, insensitive=True), |
138 | 144 | } |
139 | 145 |
|
140 | 146 | display_name = "MongoDB" |
|
0 commit comments