[FIX] core: update cache on parent_path when updated

Purpose
=======

The parent_path is invalidated from cache when computing it from scratch
(with method `_parent_store_compute`) but not when it is recomputed
(method `_parent_store_update`).

The issue is that a computed field depending on 'parent_path'
won't receive the updated value using the cache, and could lead
to inconsistencies if the developer is not aware of that.

Specification
=============

On `_parent_store_update`, set the new value of 'parent_path' in the
cache before marking the records as modified.

task-2766452

closes odoo/odoo#84795

X-original-commit: 861854a7598f31c0b971560484e3eb576af006b4
Signed-off-by: Raphael Collet <rco@odoo.com>
Signed-off-by: Rémy Voet <ryv@odoo.com>
Co-authored-by: Rémy Voet <ryv@odoo.com>
This commit is contained in:
Yannick Tivisse
2022-02-17 16:41:47 +00:00
committed by Rémy Voet (ryv)
co-authored by Rémy Voet
parent a503073b96
commit c983ae0fa2
3 changed files with 31 additions and 3 deletions
@@ -18,6 +18,7 @@ class Category(models.Model):
color = fields.Integer('Color Index')
parent = fields.Many2one('test_new_api.category', ondelete='cascade')
parent_path = fields.Char(index=True, unaccent=False)
depth = fields.Integer(compute="_compute_depth")
root_categ = fields.Many2one(_name, compute='_compute_root_categ')
display_name = fields.Char(compute='_compute_display_name', recursive=True,
inverse='_inverse_display_name')
@@ -45,6 +46,11 @@ class Category(models.Model):
current = current.parent
cat.root_categ = current
@api.depends('parent_path')
def _compute_depth(self):
for cat in self:
cat.depth = cat.parent_path.count('/') - 1
def _inverse_display_name(self):
for cat in self:
names = cat.display_name.split('/')
@@ -3063,6 +3063,24 @@ class TestParentStore(common.TransactionCase):
with self.assertRaises(UserError):
self.cats(1, 3).write({'parent': self.cats(9).id})
def test_compute_depend_parent_path(self):
self.assertEqual(self.cats(7).depth, 3)
self.assertEqual(self.cats(8).depth, 3)
self.assertEqual(self.cats(9).depth, 3)
# change parent of node to have 2 parents
self.cats(7).parent = self.cats(2)
self.assertEqual(self.cats(7).depth, 2)
# change parent of node to root
self.cats(7).parent = False
self.assertEqual(self.cats(7).depth, 0)
# change grand-parent of nodes
self.cats(6).parent = self.cats(0)
self.assertEqual(self.cats(8).depth, 2)
self.assertEqual(self.cats(9).depth, 2)
class TestRequiredMany2one(common.TransactionCase):
+7 -3
View File
@@ -4383,11 +4383,15 @@ Fields:
FROM {0} node
WHERE node.id IN %s
AND child.parent_path LIKE concat(node.parent_path, '%%')
RETURNING child.id
RETURNING child.id, child.parent_path
"""
cr.execute(query.format(self._table), [prefix, tuple(self.ids)])
modified_ids = {row[0] for row in cr.fetchall()}
self.browse(modified_ids).modified(['parent_path'])
# update the cache of updated nodes, and determine what to recompute
updated = dict(cr.fetchall())
records = self.browse(updated)
self.env.cache.update(records, self._fields['parent_path'], updated.values())
records.modified(['parent_path'])
def _load_records_write(self, values):
self.write(values)