From f386454d1302b66d0eb331ed0ae9e4811e2f3a15 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Guillermo=20Bonveh=C3=AD?= Date: Sat, 20 Jun 2020 04:33:24 -0300 Subject: [PATCH] Fixed #31728 -- Fixed cache culling when no key is found for deletion. DatabaseCache._cull implementation could fail if no key was found to perform a deletion in the table. This prevented the new cache key/value from being correctly added. --- django/core/cache/backends/db.py | 9 ++++++--- tests/cache/tests.py | 14 ++++++++++++++ 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/django/core/cache/backends/db.py b/django/core/cache/backends/db.py index 33c79c5a14..acbe702255 100644 --- a/django/core/cache/backends/db.py +++ b/django/core/cache/backends/db.py @@ -267,9 +267,12 @@ class DatabaseCache(BaseDatabaseCache): cursor.execute( connection.ops.cache_key_culling_sql() % table, [cull_num]) - cursor.execute("DELETE FROM %s " - "WHERE cache_key < %%s" % table, - [cursor.fetchone()[0]]) + last_cache_key = cursor.fetchone() + if last_cache_key: + cursor.execute( + 'DELETE FROM %s WHERE cache_key < %%s' % table, + [last_cache_key[0]], + ) def clear(self): db = router.db_for_write(self.cache_model_class) diff --git a/tests/cache/tests.py b/tests/cache/tests.py index d404475e16..dc4a221060 100644 --- a/tests/cache/tests.py +++ b/tests/cache/tests.py @@ -621,6 +621,20 @@ class BaseCacheTests: def test_zero_cull(self): self._perform_cull_test('zero_cull', 50, 19) + def test_cull_delete_when_store_empty(self): + try: + cull_cache = caches['cull'] + except InvalidCacheBackendError: + self.skipTest("Culling isn't implemented.") + old_max_entries = cull_cache._max_entries + # Force _cull to delete on first cached record. + cull_cache._max_entries = -1 + try: + cull_cache.set('force_cull_delete', 'value', 1000) + self.assertIs(cull_cache.has_key('force_cull_delete'), True) + finally: + cull_cache._max_entries = old_max_entries + def _perform_invalid_key_test(self, key, expected_warning): """ All the builtin backends should warn (except memcached that should