From 34a14480faf42fe7add69c51613985072057c9fa Mon Sep 17 00:00:00 2001 From: milosh Date: Thu, 13 Dec 2012 22:21:40 +0100 Subject: [PATCH] params clash patch --- johnny/cache.py | 9 +++++++++ johnny/tests/cache.py | 29 ++++++++++++++++++++++++++++- 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/johnny/cache.py b/johnny/cache.py index 6421231..e5bd21e 100755 --- a/johnny/cache.py +++ b/johnny/cache.py @@ -278,6 +278,15 @@ def sql_key(self, generation, sql, params, order, result_type, pieces of the query and the generation key. """ # these keys will always look pretty opaque + + # parameters have to be interleaved using simple separator + # for details, see ParamsClashBug test case + def expand_params(params): + for p in params: + yield p + yield "S" + + params = list(expand_params(params)) suffix = self.keygen.gen_key(sql, params, order, result_type) using = settings.DB_CACHE_KEYS[using] return '%s_%s_query_%s.%s' % (self.prefix, using, generation, suffix) diff --git a/johnny/tests/cache.py b/johnny/tests/cache.py index e1fc18e..095ebd8 100755 --- a/johnny/tests/cache.py +++ b/johnny/tests/cache.py @@ -23,7 +23,7 @@ def any(iterable): return False # put tests in here to be included in the testing suite -__all__ = ['MultiDbTest', 'SingleModelTest', 'MultiModelTest', 'TransactionSupportTest', 'BlackListTest', 'TransactionManagerTestCase'] +__all__ = ['MultiDbTest', 'SingleModelTest', 'MultiModelTest', 'TransactionSupportTest', 'BlackListTest', 'TransactionManagerTestCase', 'ParamsClashBug'] def _pre_setup(self): self.saved_DISABLE_SETTING = getattr(johnny_settings, 'DISABLE_QUERYSET_CACHE', False) @@ -964,3 +964,30 @@ def test_savepoint_localstore_flush(self): tm._commit_all_savepoints() # And this checks if it actually happened. self.failUnless(table_key in tm.local) + +class ParamsClashBug(QueryCacheBase): + fixtures = base.johnny_fixtures + def test_params(self): + + from testapp.models import PersonType, Person + for i in range(2, 22): + pt, _ = PersonType.objects.get_or_create(title='title %s' % i, slug='slug_%s' % i) + p = Person() + p.first_name = 'first name' + p.last_name = 'last name' + p.slug = 'person_%s' % i + p.gender = 1 + p.save() + p.person_types.add(pt) + + person_A = Person.objects.get(id = 1) + person_B = Person.objects.get(id = 12) + person_A.person_types.add(PersonType.objects.get(id = 21)) + person_B.person_types.add(PersonType.objects.get(id = 1)) + + qset = person_A.person_types.through._default_manager.values_list('persontype', flat=True) + qset_A = qset.filter(person = 1, persontype__in = [21]) + qset_B = qset.filter(person = 12, persontype__in = [1]) + + self.assertTrue(list(qset_A) == [21]) + self.assertTrue(list(qset_B) == [1])