From a0a5e0f4c83acdfc6eab69754e245354689c7185 Mon Sep 17 00:00:00 2001 From: ecogels Date: Sun, 2 May 2021 10:42:23 +0200 Subject: [PATCH] Fixed #32705 -- Prevented database cache backend from checking .rowcount on closed cursor. Co-authored-by: Mariusz Felisiak --- django/core/cache/backends/db.py | 2 +- tests/cache/tests.py | 22 ++++++++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/django/core/cache/backends/db.py b/django/core/cache/backends/db.py index acbe702255..905113903e 100644 --- a/django/core/cache/backends/db.py +++ b/django/core/cache/backends/db.py @@ -225,7 +225,7 @@ class DatabaseCache(BaseDatabaseCache): ), keys, ) - return bool(cursor.rowcount) + return bool(cursor.rowcount) def has_key(self, key, version=None): key = self.make_key(key, version=version) diff --git a/tests/cache/tests.py b/tests/cache/tests.py index 9d79e6e758..c189e26e70 100644 --- a/tests/cache/tests.py +++ b/tests/cache/tests.py @@ -24,6 +24,7 @@ from django.core.cache import ( from django.core.cache.backends.base import InvalidCacheBackendError from django.core.cache.utils import make_template_fragment_key from django.db import close_old_connections, connection, connections +from django.db.backends.utils import CursorWrapper from django.http import ( HttpRequest, HttpResponse, HttpResponseNotModified, StreamingHttpResponse, ) @@ -1116,6 +1117,27 @@ class DBCacheTests(BaseCacheTests, TransactionTestCase): with self.assertNumQueries(1): cache.delete_many(['a', 'b', 'c']) + def test_delete_cursor_rowcount(self): + """ + The rowcount attribute should not be checked on a closed cursor. + """ + class MockedCursorWrapper(CursorWrapper): + is_closed = False + + def close(self): + self.cursor.close() + self.is_closed = True + + @property + def rowcount(self): + if self.is_closed: + raise Exception('Cursor is closed.') + return self.cursor.rowcount + + cache.set_many({'a': 1, 'b': 2}) + with mock.patch('django.db.backends.utils.CursorWrapper', MockedCursorWrapper): + self.assertIs(cache.delete('a'), True) + def test_zero_cull(self): self._perform_cull_test('zero_cull', 50, 18)