From 026a0f561f5088a110dc649e4f8579746d3e2c69 Mon Sep 17 00:00:00 2001 From: Tim Zenderman Date: Tue, 13 May 2014 15:17:20 -0400 Subject: [PATCH 1/2] Add option for disabling cache on COUNT queries. --- johnny/cache.py | 8 +++++++- johnny/settings.py | 1 + 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/johnny/cache.py b/johnny/cache.py index e6dc0ae..bfc583f 100755 --- a/johnny/cache.py +++ b/johnny/cache.py @@ -299,6 +299,11 @@ def __init__(self, cache_backend=None, keyhandler=None, keygen=None): self.kg_class, self.prefix) self._patched = getattr(self, '_patched', False) + def is_count(self, sql): + if "COUNT" in sql: + return True + return False + def _monkey_select(self, original): from django.db.models.sql.constants import MULTI from django.db.models.sql.datastructures import EmptyResultSet @@ -368,7 +373,8 @@ def newfun(cls, *args, **kwargs): #no longer lazy... #todo - create a smart iterable wrapper val = list(val) - if key is not None: + #if COUNT cache is disabled and this is a COUNT, don't check the cache. + if key is not None and not (settings.DISABLE_COUNT_CACHE and self.is_count(sql)): if not val: self.cache_backend.set(key, no_result_sentinel, settings.MIDDLEWARE_SECONDS, db) else: diff --git a/johnny/settings.py b/johnny/settings.py index 7c29926..ca2c4f0 100644 --- a/johnny/settings.py +++ b/johnny/settings.py @@ -4,6 +4,7 @@ from django.core.cache import get_cache, cache DISABLE_QUERYSET_CACHE = getattr(settings, 'DISABLE_QUERYSET_CACHE', False) +DISABLE_COUNT_CACHE = getattr(settings, 'JOHNNY_DISABLE_COUNT_CACHE', False) DEFAULT_BLACKLIST = ['south_migrationhistory'] From a6bbc6b50b06e046c2d9dcfdede12744a228ca65 Mon Sep 17 00:00:00 2001 From: Tim Zenderman Date: Tue, 13 May 2014 16:05:15 -0400 Subject: [PATCH 2/2] Make sure that the val is an int so we don't affect performance on other queries with COUNT in them. --- johnny/cache.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/johnny/cache.py b/johnny/cache.py index bfc583f..df1fbff 100755 --- a/johnny/cache.py +++ b/johnny/cache.py @@ -373,8 +373,9 @@ def newfun(cls, *args, **kwargs): #no longer lazy... #todo - create a smart iterable wrapper val = list(val) - #if COUNT cache is disabled and this is a COUNT, don't check the cache. - if key is not None and not (settings.DISABLE_COUNT_CACHE and self.is_count(sql)): + #if COUNT cache is disabled, this is a query with `COUNT` in it, and `val` is a number, + #don't touch the cache. + if key is not None and not (settings.DISABLE_COUNT_CACHE and self.is_count(sql)) and not (val and type(val) == list and type(val[0]) in (long, int)): if not val: self.cache_backend.set(key, no_result_sentinel, settings.MIDDLEWARE_SECONDS, db) else: