From 8b49007a329cabe1e0e47fa748cdc80c0e4a5728 Mon Sep 17 00:00:00 2001 From: Raphael Collet Date: Wed, 16 Aug 2017 16:55:09 +0200 Subject: [PATCH] [IMP] avoid one query when recomputing a field (#18846) Specifically, instead of reading fields on `recs.exists()`, simply read those fields and catch `MissingError`. This generates around 5% less queries. --- addons/mail/models/mail_message.py | 2 +- odoo/addons/test_new_api/models.py | 2 +- .../test_new_api/tests/test_new_fields.py | 5 +++++ odoo/models.py | 18 +++++++++++++++--- 4 files changed, 22 insertions(+), 5 deletions(-) diff --git a/addons/mail/models/mail_message.py b/addons/mail/models/mail_message.py index 2970933e704..583f0320a40 100644 --- a/addons/mail/models/mail_message.py +++ b/addons/mail/models/mail_message.py @@ -665,7 +665,7 @@ class Message(models.Model): # Calculate remaining ids: if not void, raise an error other_ids = other_ids.difference(set(document_related_ids)) - if not other_ids: + if not (other_ids and self.browse(other_ids).exists()): return raise AccessError( _('The requested operation cannot be completed due to security restrictions. Please contact your system administrator.\n\n(Document type: %s, Operation: %s)') % diff --git a/odoo/addons/test_new_api/models.py b/odoo/addons/test_new_api/models.py index 2f288e89f74..85a63e47e62 100644 --- a/odoo/addons/test_new_api/models.py +++ b/odoo/addons/test_new_api/models.py @@ -356,7 +356,7 @@ class ComputeRecursive(models.Model): _name = 'test_new_api.recursive' name = fields.Char(required=True) - parent = fields.Many2one('test_new_api.recursive') + parent = fields.Many2one('test_new_api.recursive', ondelete='cascade') display_name = fields.Char(compute='_compute_display_name', store=True) @api.depends('name', 'parent.display_name') diff --git a/odoo/addons/test_new_api/tests/test_new_fields.py b/odoo/addons/test_new_api/tests/test_new_fields.py index 948470d60d6..5fecc80f1ea 100644 --- a/odoo/addons/test_new_api/tests/test_new_fields.py +++ b/odoo/addons/test_new_api/tests/test_new_fields.py @@ -202,6 +202,11 @@ class TestFields(common.TransactionCase): self.assertEqual(c.display_name, 'X / C') self.assertEqual(d.display_name, 'X / C / D') + # delete b; both c and d are deleted in cascade; c should also be marked + # to recompute, but recomputation should not fail... + b.unlink() + self.assertEqual((a + b + c + d).exists(), a) + def test_12_cascade(self): """ test computed field depending on computed field """ message = self.env.ref('test_new_api.message_0_0') diff --git a/odoo/models.py b/odoo/models.py index dd55b799f0a..81fba2863c7 100644 --- a/odoo/models.py +++ b/odoo/models.py @@ -3024,6 +3024,8 @@ class BaseModel(MetaModel('DummyModel', (object,), {'_register': False})): @api.multi def _write(self, vals): # low-level implementation of write() + if not self: + return True self.check_field_access_rights('write', list(vals)) cr = self._cr @@ -4781,13 +4783,23 @@ class BaseModel(MetaModel('DummyModel', (object,), {'_register': False})): ns = [f.name for f in fs if f.store] # evaluate fields, and group record ids by update updates = defaultdict(set) - for rec in recs.exists(): - vals = rec._convert_to_write({n: rec[n] for n in ns}) + for rec in recs: + try: + vals = {n: rec[n] for n in ns} + except MissingError: + continue + vals = rec._convert_to_write(vals) updates[frozendict(vals)].add(rec.id) # update records in batch when possible with recs.env.norecompute(): for vals, ids in pycompat.items(updates): - recs.browse(ids)._write(dict(vals)) + target = recs.browse(ids) + try: + target._write(dict(vals)) + except MissingError: + # retry without missing records + target.exists()._write(dict(vals)) + # mark computed fields as done for f in fs: recs._recompute_done(f)