summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKen Nzioka <nzioker@gmail.com>2025-10-22 10:48:23 +0300
committerJacob Walls <jacobtylerwalls@gmail.com>2025-10-24 15:51:39 -0400
commit3ff32c50d143d8a498f9a5dfef1a31b16a7456fe (patch)
tree2628df0c8f20f687559d1bd6de65d3152aad00ae
parent6fcbbe0b855d8701a4da1b65772ccf326f996b9e (diff)
Fixed #36674 -- Fixed memory leak in select_related().
-rw-r--r--django/db/models/sql/compiler.py17
-rw-r--r--tests/select_related/tests.py19
2 files changed, 27 insertions, 9 deletions
diff --git a/django/db/models/sql/compiler.py b/django/db/models/sql/compiler.py
index 0e483dc4f6..14603d5773 100644
--- a/django/db/models/sql/compiler.py
+++ b/django/db/models/sql/compiler.py
@@ -228,6 +228,13 @@ class SQLCompiler:
]
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):
"""
Return three values:
@@ -300,15 +307,7 @@ class SQLCompiler:
related_klass_infos = self.get_related_selections(select, select_mask)
klass_info["related_klass_infos"] = related_klass_infos
- def 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)
+ self.get_select_from_parent(klass_info)
ret = []
col_idx = 1
diff --git a/tests/select_related/tests.py b/tests/select_related/tests.py
index 41ed350cf3..59d1270aa0 100644
--- a/tests/select_related/tests.py
+++ b/tests/select_related/tests.py
@@ -1,6 +1,9 @@
+import gc
+
from django.core.exceptions import FieldError
from django.db.models import FETCH_PEERS
from django.test import SimpleTestCase, TestCase
+from django.test.utils import garbage_collect
from .models import (
Bookmark,
@@ -57,6 +60,17 @@ class SelectRelatedTests(TestCase):
"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):
"""
Normally, accessing FKs doesn't fill in related objects
@@ -128,6 +142,11 @@ class SelectRelatedTests(TestCase):
)
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):
"""
The optional fields passed to select_related() control which related