From e7b8e107f1cf9270cceac628cba9019e31069667 Mon Sep 17 00:00:00 2001 From: Raphael Collet Date: Tue, 2 Sep 2014 12:02:23 +0200 Subject: [PATCH] [IMP] fields: update inverse fields lazily for performance When a relational field is assigned in an onchange, its inverse field is updated in cache. Reading the current value of the inverse field may be costly, for instance in the case of a one2many field with thousands of records as a value. Instead, put in cache a SpecialValue that reads and updates the field; it will be triggered only when it is accessed. --- openerp/fields.py | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/openerp/fields.py b/openerp/fields.py index a2dd7a094f4..d0055ebcb3e 100644 --- a/openerp/fields.py +++ b/openerp/fields.py @@ -1386,13 +1386,32 @@ class Many2one(_Relational): record[self.name] = record.env[self.comodel_name].new() +class UnionUpdate(SpecialValue): + """ Placeholder for a value update; when this value is taken from the cache, + it returns ``record[field.name] | value`` and stores it in the cache. + """ + def __init__(self, field, record, value): + self.args = (field, record, value) + + def get(self): + field, record, value = self.args + # in order to read the current field's value, remove self from cache + del record._cache[field] + # read the current field's value, and update it in cache only + record._cache[field] = new_value = record[field.name] | value + return new_value + + class _RelationalMulti(_Relational): """ Abstract class for relational fields *2many. """ def _update(self, records, value): """ Update the cached value of `self` for `records` with `value`. """ for record in records: - record._cache[self] = record[self.name] | value + if self in record._cache: + record._cache[self] = record[self.name] | value + else: + record._cache[self] = UnionUpdate(self, record, value) def convert_to_cache(self, value, record, validate=True): if isinstance(value, BaseModel):