From 867c7c0451f2e67e715da5b55b5bf6696747fdc3 Mon Sep 17 00:00:00 2001 From: vishwa Date: Sun, 7 Jun 2026 10:16:27 -0400 Subject: [PATCH] Fixed #37130 -- Skipped DB cache deletion when culling offset is zero. --- django/core/cache/backends/db.py | 4 ++-- tests/cache/tests.py | 18 ++++++++++++++++++ 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/django/core/cache/backends/db.py b/django/core/cache/backends/db.py index 966312766935..3ede514b7055 100644 --- a/django/core/cache/backends/db.py +++ b/django/core/cache/backends/db.py @@ -278,8 +278,8 @@ def _cull(self, db, cursor, now, num): ) deleted_count = cursor.rowcount remaining_num = num - deleted_count - if remaining_num > self._max_entries: - cull_num = remaining_num // self._cull_frequency + cull_num = remaining_num // self._cull_frequency + if cull_num > 0 and remaining_num > self._max_entries: cursor.execute( connection.ops.cache_key_culling_sql() % table, [cull_num] ) diff --git a/tests/cache/tests.py b/tests/cache/tests.py index 4bc3e1e9cee9..6ccc8f2a3eca 100644 --- a/tests/cache/tests.py +++ b/tests/cache/tests.py @@ -1361,6 +1361,24 @@ def test_no_query_without_check(self): ) self.assertEqual(num_count_queries, 0) + def test_delete_query_skipped_on_high_cull_frequency(self): + cull_delete_cache = caches["cull"] + old_cull_freq = cull_delete_cache._cull_frequency + + # CULL_FREQUENCY > MAX_ENTRIES forces + # (remaining_num // CULL_FREQUENCY) to evaluate to zero (cull_num) + cull_delete_cache._cull_frequency = cull_delete_cache._max_entries * 2 + self.addCleanup(setattr, cull_delete_cache, "_cull_frequency", old_cull_freq) + + self._perform_cull_test("cull", 50, 49) + + with CaptureQueriesContext(connection) as captured_queries: + cull_delete_cache.set("force_cull", "value") + + # Only the expiration DELETE query runs; culling is skipped. + num_delete_queries = sum("DELETE" in query["sql"] for query in captured_queries) + self.assertEqual(num_delete_queries, 1) + def test_delete_cursor_rowcount(self): """ The rowcount attribute should not be checked on a closed cursor.