#36552: Repeating QuerySet.filter() generates unwanted LEFT OUTER JOINs
-------------------------------------+-------------------------------------
Reporter: Márton Salomváry | Type:
| Uncategorized
Status: new | Component: Database
| layer (models, ORM)
Version: 5.0 | Severity: Normal
Keywords: queryset filter | Triage Stage:
regression | Unreviewed
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
We stumbled upon this issue while upgrading a large code base from Django
4.x to 5.0.
A reasonably simplified (probably not the most trivial) reproduction case
looks like this:
{{{
Alpha.objects.filter(
bravos__charlie_bravos__charlie=9999,
)
.filter(
Exists(
Delta.objects.filter(
bravos__id=OuterRef("bravos__charlie_bravos__bravo_id"),
)
)
)
.values_list("pk")
}}}
In Django 4 the generated query is:
{{{
SELECT "example_alpha"."id"
FROM "example_alpha"
INNER JOIN "example_bravo_alphas" ON ("example_alpha"."id" =
"example_bravo_alphas"."alpha_id")
INNER JOIN "example_bravo" ON
("example_bravo_alphas"."bravo_id" = "example_bravo"."id")
INNER JOIN "example_charliebravo" ON ("example_bravo"."id" =
"example_charliebravo"."bravo_id")
WHERE ("example_charliebravo"."charlie_id" = 9999
AND EXISTS
(SELECT 1 AS "a"
FROM "example_delta" U0
INNER JOIN "example_delta_bravos" U1 ON (U0."id" =
U1."delta_id")
WHERE U1."bravo_id" =
("example_charliebravo"."bravo_id")
LIMIT 1))
}}}
In Django 5:
{{{
SELECT "example_alpha"."id"
FROM "example_alpha"
INNER JOIN "example_bravo_alphas" ON ("example_alpha"."id" =
"example_bravo_alphas"."alpha_id")
INNER JOIN "example_bravo" ON ("example_bravo_alphas"."bravo_id" =
"example_bravo"."id")
INNER JOIN "example_charliebravo" ON ("example_bravo"."id" =
"example_charliebravo"."bravo_id")
LEFT OUTER JOIN "example_bravo_alphas" T6 ON ("example_alpha"."id" =
T6."alpha_id")
LEFT OUTER JOIN "example_bravo" T7 ON (T6."bravo_id" = T7."id")
LEFT OUTER JOIN "example_charliebravo" T8 ON (T7."id" = T8."bravo_id")
WHERE ("example_charliebravo"."charlie_id" = 9999
AND EXISTS
(SELECT 1 AS "a"
FROM "example_delta" U0
INNER JOIN "example_delta_bravos" U1 ON (U0."id" =
U1."delta_id")
WHERE U1."bravo_id" = (T8."bravo_id")
LIMIT 1))
}}}
Interestingly, this QuerySet generates the expected query both in 4.x and
5.0:
{{{
Alpha.objects
.filter(
Q(bravos__charlie_bravos__charlie=9999)
&
Exists(
Delta.objects.filter(
bravos__id=OuterRef("bravos__charlie_bravos__bravo_id"),
)
)
)
.values_list("pk")
}}}
Example project for reproduction: https://github.com/salomvary/django-5
-filter-regression
The issue is also present in 5.1.x and 5.2.x.
--
Ticket URL: <https://code.djangoproject.com/ticket/36552>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.
--
You received this message because you are subscribed to the Google Groups
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To view this discussion visit
https://groups.google.com/d/msgid/django-updates/01070198a9808829-bb140502-1eaf-457f-933b-327f47a41afe-000000%40eu-central-1.amazonses.com.