Skip to content

Commit ef16085

Browse files
committed
Add unit test.
1 parent d36828c commit ef16085

File tree

1 file changed

+119
-0
lines changed

1 file changed

+119
-0
lines changed

tests/queries_/test_mql.py

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -897,3 +897,122 @@ def test_self_join_tag_three_levels_pushable(self):
897897
{"$match": {"$and": [{"name": "T1"}, {"T2.name": "T2"}, {"T3.name": "T3"}]}},
898898
],
899899
)
900+
901+
def test_partial_and_pushdown(self):
902+
a1 = Author.objects.create(name="Alice")
903+
a2 = Author.objects.create(name="Bob")
904+
b1 = Book.objects.create(title="B1", author=a1, isbn="111")
905+
Book.objects.create(title="B2", author=a2, isbn="222")
906+
cond = models.Q(author__name="Alice") & models.Q(title__contains="B")
907+
expected = [b1]
908+
with self.assertNumQueries(1) as ctx:
909+
self.assertSequenceEqual(Book.objects.filter(cond), expected)
910+
self.assertAggregateQuery(
911+
ctx.captured_queries[0]["sql"],
912+
"queries__book",
913+
[
914+
{
915+
"$lookup": {
916+
"from": "queries__author",
917+
"let": {"parent__field__0": "$author_id"},
918+
"pipeline": [
919+
{
920+
"$match": {
921+
"$and": [
922+
{
923+
"$expr": {
924+
"$and": [{"$eq": ["$$parent__field__0", "$_id"]}]
925+
}
926+
},
927+
{"name": "Alice"},
928+
]
929+
}
930+
}
931+
],
932+
"as": "queries__author",
933+
}
934+
},
935+
{"$unwind": "$queries__author"},
936+
{
937+
"$match": {
938+
"$and": [
939+
{"queries__author.name": "Alice"},
940+
{"title": {"$regex": "B", "$options": ""}},
941+
]
942+
}
943+
},
944+
],
945+
)
946+
947+
def test_not_or_demorgan_pushdown(self):
948+
a1 = Author.objects.create(name="Alice")
949+
a2 = Author.objects.create(name="Bob")
950+
b1 = Book.objects.create(title="B1", author=a1, isbn="111")
951+
Book.objects.create(title="B2", author=a2, isbn="222")
952+
expected = [b1]
953+
with self.assertNumQueries(1) as ctx:
954+
self.assertSequenceEqual(
955+
Book.objects.filter(~(models.Q(author__name="Bob") | models.Q(isbn="222"))),
956+
expected,
957+
)
958+
self.assertAggregateQuery(
959+
ctx.captured_queries[0]["sql"],
960+
"queries__book",
961+
[
962+
{
963+
"$lookup": {
964+
"from": "queries__author",
965+
"let": {"parent__field__0": "$author_id"},
966+
"pipeline": [
967+
{
968+
"$match": {
969+
"$and": [
970+
{
971+
"$expr": {
972+
"$and": [{"$eq": ["$$parent__field__0", "$_id"]}]
973+
}
974+
},
975+
{"$nor": [{"name": "Bob"}]},
976+
]
977+
}
978+
}
979+
],
980+
"as": "queries__author",
981+
}
982+
},
983+
{"$unwind": "$queries__author"},
984+
{"$match": {"$nor": [{"$or": [{"queries__author.name": "Bob"}, {"isbn": "222"}]}]}},
985+
],
986+
)
987+
988+
def test_or_mixed_local_remote_pushdown(self):
989+
a1 = Author.objects.create(name="Alice")
990+
a2 = Author.objects.create(name="Bob")
991+
b1 = Book.objects.create(title="B1", author=a1, isbn="111")
992+
b2 = Book.objects.create(title="B2", author=a2, isbn="222")
993+
cond = models.Q(title="B1") | models.Q(author__name="Bob")
994+
expected = [b1, b2]
995+
with self.assertNumQueries(1) as ctx:
996+
self.assertSequenceEqual(Book.objects.filter(cond), expected)
997+
self.assertAggregateQuery(
998+
ctx.captured_queries[0]["sql"],
999+
"queries__book",
1000+
[
1001+
{
1002+
"$lookup": {
1003+
"from": "queries__author",
1004+
"let": {"parent__field__0": "$author_id"},
1005+
"pipeline": [
1006+
{
1007+
"$match": {
1008+
"$expr": {"$and": [{"$eq": ["$$parent__field__0", "$_id"]}]}
1009+
}
1010+
}
1011+
],
1012+
"as": "queries__author",
1013+
}
1014+
},
1015+
{"$unwind": "$queries__author"},
1016+
{"$match": {"$or": [{"title": "B1"}, {"queries__author.name": "Bob"}]}},
1017+
],
1018+
)

0 commit comments

Comments
 (0)