Skip to content

Commit 4ef20d3

Browse files
committed
remove unnecessary $literal wrapping in Value.as_mql()
It only needs to wrap integers, and wrapping over types causes incorrect matching in ArrayField.
1 parent eb1e0e1 commit 4ef20d3

File tree

2 files changed

+21
-21
lines changed

2 files changed

+21
-21
lines changed

django_mongodb/expressions.py

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -204,20 +204,24 @@ def when(self, compiler, connection):
204204

205205
def value(self, compiler, connection): # noqa: ARG001
206206
value = self.value
207+
if isinstance(value, int):
208+
# Wrap numbers in $literal to prevent ambiguity when Value appears in
209+
# $project.
210+
return {"$literal": value}
207211
if isinstance(value, Decimal):
208-
value = Decimal128(value)
209-
elif isinstance(value, datetime.date):
212+
return Decimal128(value)
213+
if isinstance(value, datetime.date):
210214
# Turn dates into datetimes since BSON doesn't support dates.
211-
value = datetime.datetime.combine(value, datetime.datetime.min.time())
212-
elif isinstance(value, datetime.time):
215+
return datetime.datetime.combine(value, datetime.datetime.min.time())
216+
if isinstance(value, datetime.time):
213217
# Turn times into datetimes since BSON doesn't support times.
214-
value = datetime.datetime.combine(datetime.datetime.min.date(), value)
215-
elif isinstance(value, datetime.timedelta):
218+
return datetime.datetime.combine(datetime.datetime.min.date(), value)
219+
if isinstance(value, datetime.timedelta):
216220
# DurationField stores milliseconds rather than microseconds.
217-
value /= datetime.timedelta(milliseconds=1)
218-
elif isinstance(value, UUID):
219-
value = value.hex
220-
return {"$literal": value}
221+
return value / datetime.timedelta(milliseconds=1)
222+
if isinstance(value, UUID):
223+
return value.hex
224+
return value
221225

222226

223227
def register_expressions():

tests/expressions_/test_value.py

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -12,37 +12,33 @@ class ValueTests(SimpleTestCase):
1212
def test_date(self):
1313
self.assertEqual(
1414
Value(datetime.date(2025, 1, 1)).as_mql(None, None),
15-
{"$literal": datetime.datetime(2025, 1, 1)},
15+
datetime.datetime(2025, 1, 1),
1616
)
1717

1818
def test_datetime(self):
1919
self.assertEqual(
2020
Value(datetime.datetime(2025, 1, 1, 9, 8, 7)).as_mql(None, None),
21-
{"$literal": datetime.datetime(2025, 1, 1)},
21+
datetime.datetime(2025, 1, 1),
2222
)
2323

2424
def test_decimal(self):
25-
self.assertEqual(Value(Decimal("1.0")).as_mql(None, None), {"$literal": Decimal128("1.0")})
25+
self.assertEqual(Value(Decimal("1.0")).as_mql(None, None), Decimal128("1.0"))
2626

2727
def test_time(self):
2828
self.assertEqual(
2929
Value(datetime.time(9, 8, 7)).as_mql(None, None),
30-
{"$literal": datetime.datetime(1, 1, 1, 9, 8, 7)},
30+
datetime.datetime(1, 1, 1, 9, 8, 7),
3131
)
3232

3333
def test_timedelta(self):
34-
self.assertEqual(
35-
Value(datetime.timedelta(3600)).as_mql(None, None), {"$literal": 311040000000.0}
36-
)
34+
self.assertEqual(Value(datetime.timedelta(3600)).as_mql(None, None), 311040000000.0)
3735

3836
def test_int(self):
3937
self.assertEqual(Value(1).as_mql(None, None), {"$literal": 1})
4038

4139
def test_str(self):
42-
self.assertEqual(Value("foo").as_mql(None, None), {"$literal": "foo"})
40+
self.assertEqual(Value("foo").as_mql(None, None), "foo")
4341

4442
def test_uuid(self):
4543
value = uuid.UUID(int=1)
46-
self.assertEqual(
47-
Value(value).as_mql(None, None), {"$literal": "00000000000000000000000000000001"}
48-
)
44+
self.assertEqual(Value(value).as_mql(None, None), "00000000000000000000000000000001")

0 commit comments

Comments
 (0)