1
0
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:
Ken Nzioka
2025-10-22 10:48:23 +03:00
committed by Jacob Walls
parent 6fcbbe0b85
commit 3ff32c50d1
2 changed files with 27 additions and 9 deletions

View File

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

View File

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