Mercurial > p > roundup > code
diff roundup/cgi/templating.py @ 8125:b358da7c89e5 permission-performance
Optimize filtering of search results
Now the Permission class constructor takes an optional argument
'filter'. Now if we do not find a permission on the whole class *and*
all permission objects on the current class with a check method also
have a filter method we can improve search performance by filtering in
the database (instead of in python).
| author | Ralf Schlatterbeck <rsc@runtux.com> |
|---|---|
| date | Mon, 21 Oct 2024 16:11:13 +0200 |
| parents | 2a4d0413bd20 |
| children | f7bd22bdef9d |
line wrap: on
line diff
--- a/roundup/cgi/templating.py Fri Oct 18 18:04:46 2024 +0200 +++ b/roundup/cgi/templating.py Mon Oct 21 16:11:13 2024 +0200 @@ -3421,7 +3421,8 @@ def batch(self, permission='View'): """ Return a batch object for results from the "current search" """ - check = self._client.db.security.hasPermission + sec = self._client.db.security + check = sec.hasPermission userid = self._client.userid if not check('Web Access', userid): return Batch(self.client, [], self.pagesize, self.startwith, @@ -3454,11 +3455,34 @@ # filter for visibility item_ids = klass.filter(matches, filterspec, sort, group) - if check(permission, userid, self.classname, only_no_check = True): + cn = self.classname + if check(permission, userid, cn, only_no_check = True): allowed = item_ids else: - allowed = [id for id in item_ids - if check(permission, userid, self.classname, itemid=id)] + # Note that is_filterable returns True if no permissions are + # found. This makes it fail early (with an empty allowed list) + # instead of running through all ids with an empty + # permission list. + if sec.is_filterable(permission, userid, cn): + new_ids = set(item_ids) + confirmed = set() + for perm in sec.filter_iter(permission, userid, cn): + fargs = perm.filter(self._client.db, userid, klass) + for farg in fargs: + farg.update(sort=sort, group=group, retired=False) + result = klass.filter(list(new_ids), **farg) + new_ids.difference_update(result) + confirmed.update(result) + # all allowed? + if not new_ids: + break + # all allowed? + if not new_ids: + break + allowed = list(confirmed) + else: + allowed = [id for id in item_ids + if check(permission, userid, cn, itemid=id)] # return the batch object, using IDs only return Batch(self.client, allowed, self.pagesize, self.startwith,
