From: Raphael Collet Date: Mon, 13 Oct 2014 10:38:59 +0000 (+0200) Subject: [FIX] models: do not prefetch fields to recompute, and recompute once only X-Git-Tag: InsPy_8.0_01~4^2~25 X-Git-Url: http://git.inspyration.org/?a=commitdiff_plain;h=044ed06feccf365f92f032a50596fdb451bea4bc;p=odoo%2Fodoo.git [FIX] models: do not prefetch fields to recompute, and recompute once only The method _prefetch_field() was accidentally prefetching fields to recompute; which was skipping the actual recomputation, since a value was put in cache. But sometimes the field's value was fixed by an extra recomputation of the field. Here we remove the extra recomputation and fix the cache corruption. --- diff --git a/openerp/api.py b/openerp/api.py index a2385a8..da9e62f 100644 --- a/openerp/api.py +++ b/openerp/api.py @@ -837,11 +837,10 @@ class Environment(object): def remove_todo(self, field, records): """ Mark `field` as recomputed on `records`. """ - recs_list = self.all.todo.get(field, []) - if records in recs_list: - recs_list.remove(records) - if not recs_list: - del self.all.todo[field] + recs_list = [recs - records for recs in self.all.todo.pop(field, [])] + recs_list = filter(None, recs_list) + if recs_list: + self.all.todo[field] = recs_list def has_todo(self): """ Return whether some fields must be recomputed. """ diff --git a/openerp/models.py b/openerp/models.py index 2dcf464..1457a4b 100644 --- a/openerp/models.py +++ b/openerp/models.py @@ -3127,25 +3127,27 @@ class BaseModel(object): if len(records) > PREFETCH_MAX: records = records[:PREFETCH_MAX] | self - # by default, simply fetch field - fnames = {field.name} - - if self.env.in_draft: - # we may be doing an onchange, do not prefetch other fields - pass - elif self.env.field_todo(field): - # field must be recomputed, do not prefetch records to recompute - records -= self.env.field_todo(field) - elif not self._context.get('prefetch_fields', True): - # do not prefetch other fields - pass - elif self._columns[field.name]._prefetch: - # here we can optimize: prefetch all classic and many2one fields - fnames = set(fname + # determine which fields can be prefetched + if not self.env.in_draft and \ + self._context.get('prefetch_fields', True) and \ + self._columns[field.name]._prefetch: + # prefetch all classic and many2one fields that the user can access + fnames = {fname for fname, fcolumn in self._columns.iteritems() if fcolumn._prefetch if not fcolumn.groups or self.user_has_groups(fcolumn.groups) - ) + } + else: + fnames = {field.name} + + # important: never prefetch fields to recompute! + get_recs_todo = self.env.field_todo + for fname in list(fnames): + if get_recs_todo(self._fields[fname]): + if fname == field.name: + records -= get_recs_todo(field) + else: + fnames.discard(fname) # fetch records with read() assert self in records and field.name in fnames