diff --git a/django/db/models/sql/query.py b/django/db/models/sql/query.py index 2a14e0376f..0e54a88628 100644 --- a/django/db/models/sql/query.py +++ b/django/db/models/sql/query.py @@ -9,6 +9,7 @@ all about the internals of models in order to get the information it needs. import difflib import functools import inspect +import sys import warnings from collections import Counter, namedtuple from collections.abc import Iterator, Mapping @@ -883,7 +884,11 @@ class Query(BaseExpression): # No clashes between self and outer query should be possible. return - local_recursion_limit = 67 # explicitly avoid infinite loop + # Explicitly avoid infinite loop. The constant divider is based on how + # much depth recursive subquery references add to the stack. This value + # might need to be adjusted when adding or removing function calls from + # the code path in charge of performing these operations. + local_recursion_limit = sys.getrecursionlimit() // 16 for pos, prefix in enumerate(prefix_gen()): if prefix not in self.subq_aliases: self.alias_prefix = prefix diff --git a/tests/queries/tests.py b/tests/queries/tests.py index 80a4b51cf5..5c4e288b2a 100644 --- a/tests/queries/tests.py +++ b/tests/queries/tests.py @@ -1,5 +1,6 @@ import datetime import pickle +import sys import unittest from operator import attrgetter @@ -402,10 +403,10 @@ class Queries1Tests(TestCase): def test_avoid_infinite_loop_on_too_many_subqueries(self): x = Tag.objects.filter(pk=1) - local_recursion_limit = 67 + local_recursion_limit = sys.getrecursionlimit() // 16 msg = 'Maximum recursion depth exceeded: too many subqueries.' with self.assertRaisesMessage(RuntimeError, msg): - for i in range(local_recursion_limit * 2): + for i in range(local_recursion_limit + 2): x = Tag.objects.filter(pk__in=x) def test_reasonable_number_of_subq_aliases(self):