summaryrefslogtreecommitdiff
path: root/odoo/modules
diff options
context:
space:
mode:
authorRaphael Collet <rco@odoo.com>2019-08-27 09:51:04 +0000
committerRaphael Collet <rco@odoo.com>2019-09-09 13:18:48 +0000
commitcfb08e87b0fa8895ec4406c9b30d2ebdb790e346 (patch)
tree4ac1ff2d8a34e3fb215dfb6b562f287fea71bf34 /odoo/modules
parent3d2df88ffd5cfb9644bc54744a6c9b9a7fcfc264 (diff)
[FIX] models: use transitive triggers instead of recursion
On average, this reduces the total time spent in method `modified` by half (times measured on invoice creation and post).
Diffstat (limited to 'odoo/modules')
-rw-r--r--odoo/modules/registry.py43
1 files changed, 43 insertions, 0 deletions
diff --git a/odoo/modules/registry.py b/odoo/modules/registry.py
index c3930d3f425..8a70b8d7582 100644
--- a/odoo/modules/registry.py
+++ b/odoo/modules/registry.py
@@ -247,6 +247,49 @@ class Registry(Mapping):
for model in models:
model._setup_fields()
+ # determine field dependencies
+ Model = odoo.models.Model
+ dependencies = {
+ field: set(field.resolve_depends(model))
+ for model in models
+ if isinstance(model, Model)
+ for field in model._fields.values()
+ }
+
+ # determine transitive dependencies
+ def transitive_dependencies(field, seen=[]):
+ if field in seen:
+ return
+ for seq1 in dependencies[field]:
+ yield seq1
+ for seq2 in transitive_dependencies(seq1[-1], seen + [field]):
+ yield concat(seq1[:-1], seq2)
+
+ def concat(seq1, seq2):
+ if seq1 and seq2:
+ f1, f2 = seq1[-1], seq2[0]
+ if f1.type == 'one2many' and f2.type == 'many2one' and \
+ f1.model_name == f2.comodel_name and f1.inverse_name == f2.name:
+ return concat(seq1[:-1], seq2[1:])
+ return seq1 + seq2
+
+ # determine triggers based on transitive dependencies
+ triggers = {}
+ for field in dependencies:
+ for path in transitive_dependencies(field):
+ if path:
+ tree = triggers
+ for label in reversed(path):
+ 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)
+ }
+
for model in models:
model._setup_complete()