comparison 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
comparison
equal deleted inserted replaced
8121:2a4d0413bd20 8125:b358da7c89e5
3419 """ % (self._client.client_nonce, self.base) 3419 """ % (self._client.client_nonce, self.base)
3420 3420
3421 def batch(self, permission='View'): 3421 def batch(self, permission='View'):
3422 """ Return a batch object for results from the "current search" 3422 """ Return a batch object for results from the "current search"
3423 """ 3423 """
3424 check = self._client.db.security.hasPermission 3424 sec = self._client.db.security
3425 check = sec.hasPermission
3425 userid = self._client.userid 3426 userid = self._client.userid
3426 if not check('Web Access', userid): 3427 if not check('Web Access', userid):
3427 return Batch(self.client, [], self.pagesize, self.startwith, 3428 return Batch(self.client, [], self.pagesize, self.startwith,
3428 classname=self.classname) 3429 classname=self.classname)
3429 3430
3452 else: 3453 else:
3453 matches = None 3454 matches = None
3454 3455
3455 # filter for visibility 3456 # filter for visibility
3456 item_ids = klass.filter(matches, filterspec, sort, group) 3457 item_ids = klass.filter(matches, filterspec, sort, group)
3457 if check(permission, userid, self.classname, only_no_check = True): 3458 cn = self.classname
3459 if check(permission, userid, cn, only_no_check = True):
3458 allowed = item_ids 3460 allowed = item_ids
3459 else: 3461 else:
3460 allowed = [id for id in item_ids 3462 # Note that is_filterable returns True if no permissions are
3461 if check(permission, userid, self.classname, itemid=id)] 3463 # found. This makes it fail early (with an empty allowed list)
3464 # instead of running through all ids with an empty
3465 # permission list.
3466 if sec.is_filterable(permission, userid, cn):
3467 new_ids = set(item_ids)
3468 confirmed = set()
3469 for perm in sec.filter_iter(permission, userid, cn):
3470 fargs = perm.filter(self._client.db, userid, klass)
3471 for farg in fargs:
3472 farg.update(sort=sort, group=group, retired=False)
3473 result = klass.filter(list(new_ids), **farg)
3474 new_ids.difference_update(result)
3475 confirmed.update(result)
3476 # all allowed?
3477 if not new_ids:
3478 break
3479 # all allowed?
3480 if not new_ids:
3481 break
3482 allowed = list(confirmed)
3483 else:
3484 allowed = [id for id in item_ids
3485 if check(permission, userid, cn, itemid=id)]
3462 3486
3463 # return the batch object, using IDs only 3487 # return the batch object, using IDs only
3464 return Batch(self.client, allowed, self.pagesize, self.startwith, 3488 return Batch(self.client, allowed, self.pagesize, self.startwith,
3465 classname=self.classname) 3489 classname=self.classname)
3466 3490

Roundup Issue Tracker: http://roundup-tracker.org/