summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Manfre <mmanfre@gmail.com>2013-09-23 11:04:48 -0400
committerAnssi Kääriäinen <akaariai@gmail.com>2013-09-26 13:42:32 +0300
commita979a2fea5415849773fdfb37765ffedef6f50f2 (patch)
treea1b0af8dd9d292411a95c82ae361cbf4f5a3d68b
parentd1047c8b4cecd2e64a1ec0882328af9d081220a3 (diff)
[1.6.x] Fixed #21146 - DatabaseCache converts expires to python value
DatabaseCache uses raw cursors to bypass the ORM. This prevents it from being used by database backends that require special handling of datetime values. There is no easy way to test this, so no tests added. Backport of d5606b5763 from master
-rw-r--r--django/core/cache/backends/db.py21
1 files changed, 18 insertions, 3 deletions
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])