diff options
| author | Raphael Collet <rco@odoo.com> | 2017-07-06 17:16:03 +0200 |
|---|---|---|
| committer | Raphael Collet <rco@odoo.com> | 2017-07-10 16:18:33 +0200 |
| commit | e25bcf41e2f312536a00ef8531b2f6c6e0334ebc (patch) | |
| tree | cd4fed7e6ea124b024637c5327f0e73bce376148 /odoo/fields.py | |
| parent | c47a41b8b4c568ec63692a027c4dc13c82f1f172 (diff) | |
[REF] models: group recomputation triggers to minimize the number of requests
When several fields are modified and trigger the same recomputations, the same
SQL queries were made to determine the records to recompute, because each field
was processed independently. In order to avoid duplicated SQL queries, process
the triggers of the modified fields altogether.
This reduces the number of queries by 15% to 25%, depending on the number of
computed fields.
Diffstat (limited to 'odoo/fields.py')
| -rw-r--r-- | odoo/fields.py | 54 |
1 files changed, 0 insertions, 54 deletions
diff --git a/odoo/fields.py b/odoo/fields.py index 37c57dcd5c4..84a1d83d7a1 100644 --- a/odoo/fields.py +++ b/odoo/fields.py @@ -1063,51 +1063,6 @@ class Field(MetaField('DummyField', (object,), {})): # Notification when fields are modified # - def modified(self, records): - """ Notify that field ``self`` has been modified on ``records``: prepare the - fields/records to recompute, and return a spec indicating what to - invalidate. - """ - # invalidate the fields that depend on self, and prepare recomputation - spec = [(self, records._ids)] - - # group triggers by model and path to reduce the number of calls to search() - bymodel = defaultdict(lambda: defaultdict(list)) - for field, path in records._field_triggers[self]: - bymodel[field.model_name][path].append(field) - - for model_name, bypath in pycompat.items(bymodel): - for path, fields in pycompat.items(bypath): - if path and any(field.compute and field.store for field in fields): - # process stored fields - stored = set(field for field in fields if field.compute and field.store) - fields = set(fields) - stored - if path == 'id': - target0 = records - else: - # don't move this line to function top, see log - env = records.env(user=SUPERUSER_ID, context={'active_test': False}) - target0 = env[model_name].search([(path, 'in', records.ids)]) - if target0: - for field in stored: - # discard records to not recompute for field - target = target0 - records.env.protected(field) - if not target: - continue - spec.append((field, target._ids)) - # recompute field on target in the environment of - # records, and as user admin if required - if field.compute_sudo: - target = target.with_env(records.env(user=SUPERUSER_ID)) - else: - target = target.with_env(records.env) - target._recompute_todo(field) - # process non-stored fields - for field in fields: - spec.append((field, None)) - - return spec - def modified_draft(self, records): """ Same as :meth:`modified`, but in draft mode. """ env = records.env @@ -1898,15 +1853,6 @@ class _Relational(Field): def null(self, record): return record.env[self.comodel_name] - def modified(self, records): - # Invalidate cache for inverse fields, too. Note that the recomputation - # of fields that depend on inverse fields is already covered by the - # triggers. - spec = super(_Relational, self).modified(records) - for invf in records._field_inverses[self]: - spec.append((invf, None)) - return spec - class Many2one(_Relational): """ The value of such a field is a recordset of size 0 (no |
