Commit 73b6cf17 authored by Julien Muchembled's avatar Julien Muchembled

Cache results of category membership when search searching for predicates

parent 5f023071
...@@ -242,18 +242,26 @@ class DomainTool(BaseTool): ...@@ -242,18 +242,26 @@ class DomainTool(BaseTool):
if kw.get('src__'): if kw.get('src__'):
return sql_result_list return sql_result_list
result_list = [] result_list = []
for predicate in sql_result_list: if sql_result_list:
predicate = predicate.getObject() if test:
if (not test) or predicate.test( cache = {}
context, def isMemberOf(context, c, strict_membership):
tested_base_category_list=tested_base_category_list): if c in cache:
result_list.append(predicate) return cache[c]
if filter_method is not None: cache[c] = result = portal_categories.isMemberOf(
result_list = filter_method(result_list) context, c, strict_membership=strict_membership)
if sort_key_method is not None: return result
result_list.sort(key=sort_key_method) for predicate in sql_result_list:
elif sort_method is not None: predicate = predicate.getObject()
result_list.sort(cmp=sort_method) if not test or predicate.test(context, tested_base_category_list,
isMemberOf=isMemberOf):
result_list.append(predicate)
if filter_method is not None:
result_list = filter_method(result_list)
if sort_key_method is not None:
result_list.sort(key=sort_key_method)
elif sort_method is not None:
result_list.sort(cmp=sort_method)
return result_list return result_list
# XXX FIXME method should not be public # XXX FIXME method should not be public
......
...@@ -87,7 +87,7 @@ class Predicate(XMLObject): ...@@ -87,7 +87,7 @@ class Predicate(XMLObject):
security.declareProtected( Permissions.AccessContentsInformation, 'test' ) security.declareProtected( Permissions.AccessContentsInformation, 'test' )
def test(self, context, tested_base_category_list=None, def test(self, context, tested_base_category_list=None,
strict_membership=0, **kw): strict_membership=0, isMemberOf=None, **kw):
""" """
A Predicate can be tested on a given context. A Predicate can be tested on a given context.
Parameters can passed in order to ignore some conditions. Parameters can passed in order to ignore some conditions.
...@@ -97,6 +97,9 @@ class Predicate(XMLObject): ...@@ -97,6 +97,9 @@ class Predicate(XMLObject):
destination or the source of a predicate. destination or the source of a predicate.
- if strict_membership is specified, we should make sure that we - if strict_membership is specified, we should make sure that we
are strictly a member of tested categories are strictly a member of tested categories
- isMemberOf can be a function caching results for
CategoryTool.isMemberOf: it is always called with given 'context' and
'strict_membership' values, and different categories.
""" """
self = self.asPredicate() self = self.asPredicate()
if self is None: if self is None:
...@@ -150,17 +153,19 @@ class Predicate(XMLObject): ...@@ -150,17 +153,19 @@ class Predicate(XMLObject):
# Test category memberships. Enable the read-only transaction cache # Test category memberships. Enable the read-only transaction cache
# because this part is strictly read-only, and context.isMemberOf # because this part is strictly read-only, and context.isMemberOf
# is very expensive when the category list has many items. # is very expensive when the category list has many items.
if isMemberOf is None:
isMemberOf = context._getCategoryTool().isMemberOf
with readOnlyTransactionCache(): with readOnlyTransactionCache():
for c in self.getMembershipCriterionCategoryList(): for c in self.getMembershipCriterionCategoryList():
bc = c.split('/', 1)[0] bc = c.split('/', 1)[0]
if tested_base_category_list is None or bc in tested_base_category_list: if tested_base_category_list is None or bc in tested_base_category_list:
if bc in multimembership_criterion_base_category_list: if bc in multimembership_criterion_base_category_list:
if not context.isMemberOf(c, strict_membership=strict_membership): if not isMemberOf(context, c, strict_membership=strict_membership):
return 0 return 0
elif bc in membership_criterion_base_category_list and \ elif bc in membership_criterion_base_category_list and \
not tested_base_category.get(bc): not tested_base_category.get(bc):
tested_base_category[bc] = \ tested_base_category[bc] = \
context.isMemberOf(c, strict_membership=strict_membership) isMemberOf(context, c, strict_membership=strict_membership)
if 0 in tested_base_category.itervalues(): if 0 in tested_base_category.itervalues():
return 0 return 0
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment