diff options
| author | Simon Charette <charette.s@gmail.com> | 2023-06-14 00:28:42 -0400 |
|---|---|---|
| committer | Mariusz Felisiak <felisiak.mariusz@gmail.com> | 2023-06-14 09:44:49 +0200 |
| commit | 1c4f5f314e2b0c77b3fa0c75f703218e7e06f4be (patch) | |
| tree | be0bfb46870001c7955702e04c3dedf23f5e0415 | |
| parent | cfc9c94d97edf9aaea647bbecc89a791cf7ec0b8 (diff) | |
Refs #32143 -- Removed superflous constraints on excluded query.
The outer query reference is not necessary when alias can be reused and
can even be harmful by confusing query planers.
Refs #34597.
| -rw-r--r-- | django/db/models/sql/query.py | 7 | ||||
| -rw-r--r-- | tests/queries/tests.py | 13 |
2 files changed, 15 insertions, 5 deletions
diff --git a/django/db/models/sql/query.py b/django/db/models/sql/query.py index 12066cd4f8..13a6809dd8 100644 --- a/django/db/models/sql/query.py +++ b/django/db/models/sql/query.py @@ -2020,10 +2020,11 @@ class Query(BaseExpression): lookup = lookup_class(pk.get_col(query.select[0].alias), pk.get_col(alias)) query.where.add(lookup, AND) query.external_aliases[alias] = True + else: + lookup_class = select_field.get_lookup("exact") + lookup = lookup_class(col, ResolvedOuterRef(trimmed_prefix)) + query.where.add(lookup, AND) - lookup_class = select_field.get_lookup("exact") - lookup = lookup_class(col, ResolvedOuterRef(trimmed_prefix)) - query.where.add(lookup, AND) condition, needed_inner = self.build_filter(Exists(query)) if contains_louter: diff --git a/tests/queries/tests.py b/tests/queries/tests.py index 9578777b11..43cfd9b7c0 100644 --- a/tests/queries/tests.py +++ b/tests/queries/tests.py @@ -3231,7 +3231,7 @@ class ExcludeTests(TestCase): [self.r2], ) - def test_ticket14511(self): + def test_exclude_m2m_through(self): alex = Person.objects.get_or_create(name="Alex")[0] jane = Person.objects.get_or_create(name="Jane")[0] @@ -3267,7 +3267,16 @@ class ExcludeTests(TestCase): .distinct() .order_by("name") ) - self.assertSequenceEqual(alex_nontech_employers, [google, intel, microsoft]) + with self.assertNumQueries(1) as ctx: + self.assertSequenceEqual(alex_nontech_employers, [google, intel, microsoft]) + sql = ctx.captured_queries[0]["sql"] + # Company's ID should appear in SELECT and INNER JOIN, not in EXISTS as + # the outer query reference is not necessary when an alias is reused. + company_id = "%s.%s" % ( + connection.ops.quote_name(Company._meta.db_table), + connection.ops.quote_name(Company._meta.get_field("id").column), + ) + self.assertEqual(sql.count(company_id), 2) def test_exclude_reverse_fk_field_ref(self): tag = Tag.objects.create() |
