diff options
| -rw-r--r-- | odoo/addons/test_performance/tests/test_performance.py | 18 | ||||
| -rw-r--r-- | odoo/fields.py | 8 |
2 files changed, 24 insertions, 2 deletions
diff --git a/odoo/addons/test_performance/tests/test_performance.py b/odoo/addons/test_performance/tests/test_performance.py index 7ace0d3ea96..e880f8a3c75 100644 --- a/odoo/addons/test_performance/tests/test_performance.py +++ b/odoo/addons/test_performance/tests/test_performance.py @@ -535,3 +535,21 @@ class TestIrPropertyOptimizations(TransactionCase): with self.assertQueryCount(5): self.Bacon.create({'property_eggs': False}) + + +@tagged('mapped_perf') +class TestMapped(TransactionCase): + + def test_relational_mapped(self): + # create 1000 records with one line each + recs = self.env['test_performance.base'].create([ + {'name': 'foo%d' % index, 'line_ids': [(0, 0, {'value': index})]} + for index in range(1000) + ]) + recs.flush() + recs.invalidate_cache() + + # expected same performance as recs.line_ids.mapped('value') + with self.assertQueryCount(3): + for rec in recs: + rec.line_ids.mapped('value') diff --git a/odoo/fields.py b/odoo/fields.py index 6ad32a505b6..31d67bc6556 100644 --- a/odoo/fields.py +++ b/odoo/fields.py @@ -1018,8 +1018,12 @@ class Field(MetaField('DummyField', (object,), {})): # retrieve values in cache, and fetch missing ones vals = records.env.cache.get_until_miss(records, self) while len(vals) < len(records): - # trigger prefetching on remaining records, and continue retrieval - remaining = records[len(vals):] + # It is important to construct a 'remaining' recordset with the + # _prefetch_ids of the original recordset, in order to prefetch as + # many records as possible. If not done this way, scenarios such as + # [rec.line_ids.mapped('name') for rec in recs] would generate one + # query per record in `recs`! + remaining = records._browse(records.env, records[len(vals):]._ids, records._prefetch_ids) self.__get__(first(remaining), type(remaining)) vals += records.env.cache.get_until_miss(remaining, self) |
