From 785018cc9c6429eb79b09ae84c9c28c9da24f85a Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Thu, 10 Jul 2014 13:43:45 +0200 Subject: [PATCH] [FIX] only prefetch other cached records with read field uncached during _read_from_database If expansion of the recordset is done during _prefetch_field, if one of the prefetches (not the base record(s) but one of those selected by BaseModel._in_cache_without) can't be read by the current user (due to an access rule or for field reading reasons, or whatever) the whole read is failed, even if the record which was specifically asked for could be read on its own. By only expanding the read set in _read_from_database, the cache is correctly set but read() and _prefetch_field() only check the records explicitly asked for for AccessDenied, prefetched records will only be asked if they are ever accessed. fixes #1013 --- openerp/models.py | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/openerp/models.py b/openerp/models.py index a801257b81e..73b0981f513 100644 --- a/openerp/models.py +++ b/openerp/models.py @@ -3101,10 +3101,10 @@ class BaseModel(object): instance) for `self` in cache. """ # fetch the records of this model without field_name in their cache - records = self._in_cache_without(field) + records = self # by default, simply fetch field - fnames = set((field.name,)) + fnames = {field.name} if self.pool._init: # columns may be missing from database, do not prefetch other fields @@ -3176,8 +3176,14 @@ class BaseModel(object): 'order': self._parent_order or self._order, } + empty = self.browse() + records = self.browse(set(itertools.chain.from_iterable( + (self._in_cache_without(field) - self.env.todo.get(field, empty)).ids + for field in (self._fields[name] for name in field_names) + ))) + result = [] - for sub_ids in cr.split_for_in_conditions(self.ids): + for sub_ids in cr.split_for_in_conditions(records.ids): cr.execute(query, [tuple(sub_ids)] + rule_params) result.extend(cr.dictfetchall()) @@ -3250,9 +3256,9 @@ class BaseModel(object): # store failed values in cache for the records that could not be read fetched = self.browse(ids) - missing = self - fetched + missing = records - fetched if missing: - extras = fetched - self + extras = fetched - records if extras: raise AccessError( _("Database fetch misses ids ({}) and has extra ids ({}), may be caused by a type incoherence in a previous request").format(