summaryrefslogtreecommitdiff
path: root/odoo/fields.py
diff options
context:
space:
mode:
authorRaphael Collet <rco@odoo.com>2017-10-09 11:53:18 +0200
committerGitHub <noreply@github.com>2017-10-09 11:53:18 +0200
commitcb1cfadda23cc1e1d73f4ef854ec82c294febd09 (patch)
treefc871e6730973a62dfc76690a2a7ae92442b02c1 /odoo/fields.py
parent7c68e4d0407a2659378dd33e5fedc2f12270c112 (diff)
[FIX] fields: performance issue in `copy_cache` (#19963)
That function is called when computing related fields in onchange mode. The new implementation makes a direct access to the cache's implementation. opw-772303
Diffstat (limited to 'odoo/fields.py')
-rw-r--r--odoo/fields.py27
1 files changed, 16 insertions, 11 deletions
diff --git a/odoo/fields.py b/odoo/fields.py
index 745e5effb62..60aefa9bc25 100644
--- a/odoo/fields.py
+++ b/odoo/fields.py
@@ -53,18 +53,23 @@ def _check_value(value):
def copy_cache(records, env):
""" Recursively copy the cache of ``records`` to the environment ``env``. """
- todo, done = set(records), set()
+ src = records.env
+ todo = defaultdict(set) # {model_name: ids}
+ done = defaultdict(set) # {model_name: ids}
+ todo[records._name].update(records._ids)
while todo:
- record = todo.pop()
- if record not in done:
- done.add(record)
- target = record.with_env(env)
- for name in record._cache:
- field = record._fields[name]
- value = record[name]
- if isinstance(value, BaseModel):
- todo.update(value)
- target._cache[name] = field.convert_to_cache(value, target, validate=False)
+ model_name = next(iter(todo))
+ record_ids = todo.pop(model_name) - done[model_name]
+ done[model_name].update(record_ids)
+ for name, field in src[model_name]._fields.items():
+ src_cache = src.cache[field]
+ dst_cache = env.cache[field]
+ for record_id in record_ids:
+ if record_id in src_cache:
+ # copy the cached value as such
+ value = dst_cache[record_id] = src_cache[record_id]
+ if field.relational and isinstance(value, tuple):
+ todo[field.comodel_name].update(value)
def resolve_mro(model, name, predicate):