diff --git a/django/core/cache/backends/db.py b/django/core/cache/backends/db.py index 0e59c6d65e..8844bc8f61 100644 --- a/django/core/cache/backends/db.py +++ b/django/core/cache/backends/db.py @@ -11,6 +11,7 @@ except ImportError: from django.conf import settings from django.core.cache.backends.base import BaseCache, DEFAULT_TIMEOUT from django.db import connections, transaction, router, DatabaseError +from django.db.backends.utils import typecast_timestamp from django.utils import timezone, six from django.utils.encoding import force_bytes @@ -65,8 +66,13 @@ class DatabaseCache(BaseDatabaseCache): if row is None: return default now = timezone.now() - - if row[2] < now: + expires = row[2] + if connections[db].features.needs_datetime_string_cast and not isinstance(expires, datetime): + # Note: typecasting is needed by some 3rd party database backends. + # All core backends work without typecasting, so be careful about + # changes here - test suite will NOT pick regressions here. + expires = typecast_timestamp(str(expires)) + if expires < now: db = router.db_for_write(self.cache_model_class) cursor = connections[db].cursor() cursor.execute("DELETE FROM %s " @@ -112,12 +118,21 @@ class DatabaseCache(BaseDatabaseCache): if six.PY3: b64encoded = b64encoded.decode('latin1') try: + # Note: typecasting for datetimes is needed by some 3rd party + # database backends. All core backends work without typecasting, + # so be careful about changes here - test suite will NOT pick + # regressions. with transaction.atomic(using=db): cursor.execute("SELECT cache_key, expires FROM %s " "WHERE cache_key = %%s" % table, [key]) result = cursor.fetchone() + if result: + current_expires = result[1] + if (connections[db].features.needs_datetime_string_cast and not + isinstance(current_expires, datetime)): + current_expires = typecast_timestamp(str(current_expires)) exp = connections[db].ops.value_to_db_datetime(exp) - if result and (mode == 'set' or (mode == 'add' and result[1] < now)): + if result and (mode == 'set' or (mode == 'add' and current_expires < now)): cursor.execute("UPDATE %s SET value = %%s, expires = %%s " "WHERE cache_key = %%s" % table, [b64encoded, exp, key])