From 8b4a43dda702fe72c254388f1be2c0c75b7a3efc Mon Sep 17 00:00:00 2001 From: Simon Charette Date: Thu, 15 Aug 2019 23:20:57 -0400 Subject: [PATCH] Fixed #29545 -- Fixed using filter lookups againts nested subquery expressions. Made sql.Where resolve lhs of its child nodes. This is necessary to allow filter lookups against nested subquery expressions to properly resolve their OuterRefs to Cols. Thanks Oskar Persson for the simplified test case. --- django/db/models/sql/where.py | 12 +++++++----- tests/lookup/tests.py | 14 ++++++++++++++ 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/django/db/models/sql/where.py b/django/db/models/sql/where.py index 496822c58b..bf0828dc8b 100644 --- a/django/db/models/sql/where.py +++ b/django/db/models/sql/where.py @@ -184,18 +184,20 @@ class WhereNode(tree.Node): return any(child.is_summary for child in self.children) @staticmethod - def _resolve_rhs(rhs, query, *args, **kwargs): - if hasattr(rhs, 'resolve_expression'): - rhs = rhs.resolve_expression(query, *args, **kwargs) - return rhs + def _resolve_leaf(expr, query, *args, **kwargs): + if hasattr(expr, 'resolve_expression'): + expr = expr.resolve_expression(query, *args, **kwargs) + return expr @classmethod def _resolve_node(cls, node, query, *args, **kwargs): if hasattr(node, 'children'): for child in node.children: cls._resolve_node(child, query, *args, **kwargs) + if hasattr(node, 'lhs'): + node.lhs = cls._resolve_leaf(node.lhs, query, *args, **kwargs) if hasattr(node, 'rhs'): - node.rhs = cls._resolve_rhs(node.rhs, query, *args, **kwargs) + node.rhs = cls._resolve_leaf(node.rhs, query, *args, **kwargs) def resolve_expression(self, *args, **kwargs): clone = self.clone() diff --git a/tests/lookup/tests.py b/tests/lookup/tests.py index 7bf436ad7a..a603824c0d 100644 --- a/tests/lookup/tests.py +++ b/tests/lookup/tests.py @@ -942,3 +942,17 @@ class LookupTests(TestCase): pk_exists=Exists(qs), ) self.assertCountEqual(seasons, Season.objects.all()) + + def test_nested_outerref_lhs(self): + tag = Tag.objects.create(name=self.au1.alias) + tag.articles.add(self.a1) + qs = Tag.objects.annotate( + has_author_alias_match=Exists( + Article.objects.annotate( + author_exists=Exists( + Author.objects.filter(alias=OuterRef(OuterRef('name'))) + ), + ).filter(author_exists=True) + ), + ) + self.assertEqual(qs.get(has_author_alias_match=True), tag)