[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) <rco@openerp.com>
This commit is contained in:
Raphael Collet
2019-09-09 13:18:53 +00:00
parent cfb08e87b0
commit 263849c336
3 changed files with 14 additions and 17 deletions
+1 -1
View File
@@ -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])
+12 -10
View File
@@ -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
+1 -6
View File
@@ -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()