summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--django/core/cache/backends/db.py4
-rw-r--r--tests/cache/tests.py18
2 files changed, 20 insertions, 2 deletions
diff --git a/django/core/cache/backends/db.py b/django/core/cache/backends/db.py
index 9663127669..3ede514b70 100644
--- a/django/core/cache/backends/db.py
+++ b/django/core/cache/backends/db.py
@@ -278,8 +278,8 @@ class DatabaseCache(BaseDatabaseCache):
)
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 4bc3e1e9ce..6ccc8f2a3e 100644
--- a/tests/cache/tests.py
+++ b/tests/cache/tests.py
@@ -1361,6 +1361,24 @@ class DBCacheTests(BaseCacheTests, TransactionTestCase):
)
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.