mirror of
https://github.com/django/django.git
synced 2025-10-31 09:41:08 +00:00
Fixed #36674 -- Fixed memory leak in select_related().
This commit is contained in:
@@ -228,6 +228,13 @@ class SQLCompiler:
|
|||||||
]
|
]
|
||||||
return expressions
|
return expressions
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_select_from_parent(cls, klass_info):
|
||||||
|
for ki in klass_info["related_klass_infos"]:
|
||||||
|
if ki["from_parent"]:
|
||||||
|
ki["select_fields"] = klass_info["select_fields"] + ki["select_fields"]
|
||||||
|
cls.get_select_from_parent(ki)
|
||||||
|
|
||||||
def get_select(self, with_col_aliases=False):
|
def get_select(self, with_col_aliases=False):
|
||||||
"""
|
"""
|
||||||
Return three values:
|
Return three values:
|
||||||
@@ -300,15 +307,7 @@ class SQLCompiler:
|
|||||||
related_klass_infos = self.get_related_selections(select, select_mask)
|
related_klass_infos = self.get_related_selections(select, select_mask)
|
||||||
klass_info["related_klass_infos"] = related_klass_infos
|
klass_info["related_klass_infos"] = related_klass_infos
|
||||||
|
|
||||||
def get_select_from_parent(klass_info):
|
self.get_select_from_parent(klass_info)
|
||||||
for ki in klass_info["related_klass_infos"]:
|
|
||||||
if ki["from_parent"]:
|
|
||||||
ki["select_fields"] = (
|
|
||||||
klass_info["select_fields"] + ki["select_fields"]
|
|
||||||
)
|
|
||||||
get_select_from_parent(ki)
|
|
||||||
|
|
||||||
get_select_from_parent(klass_info)
|
|
||||||
|
|
||||||
ret = []
|
ret = []
|
||||||
col_idx = 1
|
col_idx = 1
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
|
import gc
|
||||||
|
|
||||||
from django.core.exceptions import FieldError
|
from django.core.exceptions import FieldError
|
||||||
from django.db.models import FETCH_PEERS
|
from django.db.models import FETCH_PEERS
|
||||||
from django.test import SimpleTestCase, TestCase
|
from django.test import SimpleTestCase, TestCase
|
||||||
|
from django.test.utils import garbage_collect
|
||||||
|
|
||||||
from .models import (
|
from .models import (
|
||||||
Bookmark,
|
Bookmark,
|
||||||
@@ -57,6 +60,17 @@ class SelectRelatedTests(TestCase):
|
|||||||
"Amanita muscaria"
|
"Amanita muscaria"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def setup_gc_debug(self):
|
||||||
|
self.addCleanup(gc.set_debug, 0)
|
||||||
|
self.addCleanup(gc.enable)
|
||||||
|
gc.disable()
|
||||||
|
garbage_collect()
|
||||||
|
gc.set_debug(gc.DEBUG_SAVEALL)
|
||||||
|
|
||||||
|
def assert_no_memory_leaks(self):
|
||||||
|
garbage_collect()
|
||||||
|
self.assertEqual(gc.garbage, [])
|
||||||
|
|
||||||
def test_access_fks_without_select_related(self):
|
def test_access_fks_without_select_related(self):
|
||||||
"""
|
"""
|
||||||
Normally, accessing FKs doesn't fill in related objects
|
Normally, accessing FKs doesn't fill in related objects
|
||||||
@@ -128,6 +142,11 @@ class SelectRelatedTests(TestCase):
|
|||||||
)
|
)
|
||||||
self.assertEqual(s.id + 10, s.a)
|
self.assertEqual(s.id + 10, s.a)
|
||||||
|
|
||||||
|
def test_select_related_memory_leak(self):
|
||||||
|
self.setup_gc_debug()
|
||||||
|
list(Species.objects.select_related("genus"))
|
||||||
|
self.assert_no_memory_leaks()
|
||||||
|
|
||||||
def test_certain_fields(self):
|
def test_certain_fields(self):
|
||||||
"""
|
"""
|
||||||
The optional fields passed to select_related() control which related
|
The optional fields passed to select_related() control which related
|
||||||
|
|||||||
Reference in New Issue
Block a user