summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRaphael Collet <rco@openerp.com>2014-10-13 12:38:59 +0200
committerRaphael Collet <rco@openerp.com>2014-10-13 12:38:59 +0200
commit044ed06feccf365f92f032a50596fdb451bea4bc (patch)
treed45720ee046e45f9ef711dc2356cdb4cc45a0e86
parentcfa04b1d3da30ff6628f8f3fe488bf7d18015348 (diff)
[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.
-rw-r--r--openerp/api.py9
-rw-r--r--openerp/models.py34
2 files changed, 22 insertions, 21 deletions
diff --git a/openerp/api.py b/openerp/api.py
index a2385a8b109..da9e62f1549 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 2dcf464a925..1457a4beecf 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