Refs #27149 -- Based recursive nested subquery detection on sys.getrecursionlimit().

This makes sure the test_avoid_infinite_loop_on_too_many_subqueries test
doesn't fail on systems with a non-default recursion limit.
This commit is contained in:
Simon Charette 2019-04-05 00:37:58 -04:00 committed by Mariusz Felisiak
parent 9ac8520fcd
commit c0969ee227
2 changed files with 9 additions and 3 deletions

View File

@ -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

View File

@ -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):