[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.
This commit is contained in:
@@ -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)') %
|
||||
|
||||
@@ -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')
|
||||
|
||||
@@ -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')
|
||||
|
||||
+15
-3
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user