From 263849c3365af3d62fa5b9ceaff65b2f7b84c092 Mon Sep 17 00:00:00 2001 From: Raphael Collet Date: Tue, 27 Aug 2019 13:27:51 +0000 Subject: [PATCH] [FIX] models: optimize modified() in the context of record creation This prevents a bunch of queries that are useless when creating a record. Indeed, right after a record has been created, no other record has a many2one reference to it. In other words, inversing a many2one field from the record just created always gives an empty recordset. Those useless inversions generate about a dozen queries when creating a `res.partner`, for instance. This saves queries, but not much time. closes odoo/odoo#36566 Signed-off-by: Raphael Collet (rco) --- odoo/fields.py | 2 +- odoo/models.py | 22 ++++++++++++---------- odoo/modules/registry.py | 7 +------ 3 files changed, 14 insertions(+), 17 deletions(-) diff --git a/odoo/fields.py b/odoo/fields.py index 995a586739f..9a3b3504a2b 100644 --- a/odoo/fields.py +++ b/odoo/fields.py @@ -1072,7 +1072,7 @@ class Field(MetaField('DummyField', (object,), {})): if new_records: # new records: no business logic with records.env.protecting(records._field_computed.get(self, [self]), records): - new_records.modified([self.name], create=True) + new_records.modified([self.name]) self.write(new_records, value) if self.relational: new_records.modified([self.name]) diff --git a/odoo/models.py b/odoo/models.py index d568e79d5e2..b35ee16ba6b 100644 --- a/odoo/models.py +++ b/odoo/models.py @@ -2651,7 +2651,6 @@ class BaseModel(MetaModel('DummyModel', (object,), {'_register': False})): # - mark I to recompute on inverse(W, inverse(X, records)), # - mark J to recompute on inverse(Y, records). cls._field_triggers = cls.pool.field_triggers - cls._field_triggers_create = cls.pool.field_triggers_create # register constraints and onchange methods cls._init_constraints_onchanges() @@ -5493,20 +5492,19 @@ Record ids: %(records)s """ if not self or not fnames: return - field_triggers = self._field_triggers if not create else self._field_triggers_create if len(fnames) == 1: - tree = field_triggers.get(self._fields[next(iter(fnames))]) + tree = self._field_triggers.get(self._fields[next(iter(fnames))]) else: # merge dependency trees to evaluate all triggers at once tree = {} for fname in fnames: - node = field_triggers.get(self._fields[fname]) + node = self._field_triggers.get(self._fields[fname]) if node: trigger_tree_merge(tree, node) if tree: - self.sudo()._modified_triggers(tree) + self.sudo()._modified_triggers(tree, create) - def _modified_triggers(self, tree): + def _modified_triggers(self, tree, create=False): """ Process a tree of field triggers on ``self``. """ if not self: return @@ -5519,17 +5517,21 @@ Record ids: %(records)s continue # Dont force the recomputation of compute fields which are # not stored as this is not really necessary. + recursive = not create and field.recursive if field.compute and field.store: - if field.recursive: + if recursive: added = self.env.not_to_compute(field, records) self.env.add_to_compute(field, records) else: - if field.recursive: + if recursive: added = self & self.env.cache.get_records(self, field) self.env.cache.invalidate([(field, records._ids)]) # recursively trigger recomputation of field's dependents - if field.recursive: + if recursive: added.modified([field.name]) + elif create and key.type in ('many2one', 'many2one_reference'): + # upon creation, no other record has a reference to self + continue else: # val is another tree of dependencies model = self.env[key.model_name] @@ -5617,7 +5619,7 @@ Record ids: %(records)s yield from val else: yield from traverse(val) - return traverse(self._field_triggers_create.get(field, {})) + return traverse(self._field_triggers.get(field, {})) def _has_onchange(self, field, other_fields): """ Return whether ``field`` should trigger an onchange event in the diff --git a/odoo/modules/registry.py b/odoo/modules/registry.py index 8a70b8d7582..5df1a7b61f0 100644 --- a/odoo/modules/registry.py +++ b/odoo/modules/registry.py @@ -283,12 +283,7 @@ class Registry(Mapping): tree = tree.setdefault(label, {}) tree.setdefault(None, set()).add(field) - self.field_triggers_create = triggers - self.field_triggers = { - field: tree - for field, tree in triggers.items() - if not (field.type == 'one2many' and field.inverse) - } + self.field_triggers = triggers for model in models: model._setup_complete()