From 6fbce45b0376f0ec8f3bf244f4f1f8d62c201f58 Mon Sep 17 00:00:00 2001 From: Hasan Ramezani Date: Fri, 3 Apr 2020 11:05:10 +0200 Subject: [PATCH] Fixed #31415 -- Fixed crash when nested OuterRef is used with operators or in database functions. --- django/db/models/expressions.py | 3 +++ tests/expressions/tests.py | 18 +++++++++++++++++- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/django/db/models/expressions.py b/django/db/models/expressions.py index 4753a258f92c8..8d37c457ce3d6 100644 --- a/django/db/models/expressions.py +++ b/django/db/models/expressions.py @@ -585,6 +585,9 @@ def resolve_expression(self, *args, **kwargs): return self.name return ResolvedOuterRef(self.name) + def relabeled_clone(self, relabels): + return self + class Func(SQLiteNumericMixin, Expression): """An SQL function call.""" diff --git a/tests/expressions/tests.py b/tests/expressions/tests.py index 07c70ee9e9332..0fac4642f76ba 100644 --- a/tests/expressions/tests.py +++ b/tests/expressions/tests.py @@ -15,7 +15,7 @@ ) from django.db.models.expressions import Col, Combinable, Random, RawSQL, Ref from django.db.models.functions import ( - Coalesce, Concat, Length, Lower, Substr, Upper, + Coalesce, Concat, Left, Length, Lower, Substr, Upper, ) from django.db.models.sql import constants from django.db.models.sql.datastructures import Join @@ -648,6 +648,22 @@ def test_outerref_with_operator(self): outer = Company.objects.filter(pk__in=Subquery(inner.values('pk'))) self.assertEqual(outer.get().name, 'Test GmbH') + def test_nested_outerref_with_function(self): + self.gmbh.point_of_contact = Employee.objects.get(lastname='Meyer') + self.gmbh.save() + inner = Employee.objects.filter( + lastname__startswith=Left(OuterRef(OuterRef('lastname')), 1), + ) + qs = Employee.objects.annotate( + ceo_company=Subquery( + Company.objects.filter( + point_of_contact__in=inner, + ceo__pk=OuterRef('pk'), + ).values('name'), + ), + ).filter(ceo_company__isnull=False) + self.assertEqual(qs.get().ceo_company, 'Test GmbH') + def test_annotation_with_outerref(self): gmbh_salary = Company.objects.annotate( max_ceo_salary_raise=Subquery(