From d3703ecb4cbd3ca4c208910c031ae2fadc4b321b Mon Sep 17 00:00:00 2001 From: Denis Vermylen Date: Thu, 9 Feb 2017 15:29:20 +0100 Subject: [PATCH] [IMP] models: avoid searching by id in read_group When using read_group() and grouping by many2one fields, the many2one groupby fields get updated from an integer id to a tuple from name_get() at the end of the method. e.g.: {'user_id': 1, ...} -> {'user_id': (1, u'Administrator'), ...} To do this, it reads the many2one field by browsing on self. When self is a model with _auto = False (typically an SQL view), searching by id can be costly as the id column may not have usual properties for performance (in some cases a full computation of the table is required to look up 1 id). --- odoo/models.py | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/odoo/models.py b/odoo/models.py index f511b7cce33..0a31ce1d044 100644 --- a/odoo/models.py +++ b/odoo/models.py @@ -2025,13 +2025,7 @@ class BaseModel(object): if not groupby_fields: return fetched_data - many2onefields = [gb['field'] for gb in annotated_groupbys if gb['type'] == 'many2one'] - if many2onefields: - data_ids = [r['id'] for r in fetched_data] - many2onefields = list(set(many2onefields)) - data_dict = {d['id']: d for d in self.browse(data_ids).read(many2onefields)} - for d in fetched_data: - d.update(data_dict[d['id']]) + self._read_group_resolve_many2one_fields(fetched_data, annotated_groupbys) data = map(lambda r: {k: self._read_group_prepare_data(k,v, groupby_dict) for k,v in r.iteritems()}, fetched_data) result = [self._read_group_format_result(d, annotated_groupbys, groupby, domain) for d in data] @@ -2046,6 +2040,15 @@ class BaseModel(object): ) return result + def _read_group_resolve_many2one_fields(self, data, fields): + many2onefields = {field['field'] for field in fields if field['type'] == 'many2one'} + for field in many2onefields: + ids_set = {d[field] for d in data} + m2o_records = self.env[self._fields[field].comodel_name].browse(ids_set) + data_dict = dict(m2o_records.name_get()) + for d in data: + d[field] = (d[field], data_dict[d[field]]) if d[field] else False + def _inherits_join_add(self, current_model, parent_model_name, query): """ Add missing table SELECT and JOIN clause to ``query`` for reaching the parent table (no duplicates)