[FIX] core: update inverse of many2many in order

Consider two models A and B, a many2many field F from A to B and its
inverse relation G from B to A.  When F is modified, G is updated
accordingly in cache.  The statement

    records.write({F: [Command.link(b.id)]})

is expected to add b.id to records.F, and add records.ids to b.G.  In
order to avoid nondeterminism, the additions should be done at the end
of the recordset, and in order.  In other words, if none of "records"
are in b.G, then after the statement above, b.G should be updated as

    b.G = b.G + records

This patch ensures that "records" are added in order.

closes odoo/odoo#94909

X-original-commit: b8fbc460673827497f6817e1751b5d365d8ae29a
Signed-off-by: Vincent Schippefilt (vsc) <vsc@odoo.com>
Signed-off-by: Raphael Collet <rco@odoo.com>
This commit is contained in:
Raphael Collet
2022-06-30 09:29:58 +02:00
parent 31d03da243
commit c0fea2cec8
2 changed files with 29 additions and 1 deletions
@@ -2125,6 +2125,34 @@ class TestFields(TransactionCaseWithUserDemo):
moves = self.env['test_new_api.move'].search([('line_ids', 'in', line.id)])
self.assertEqual(moves, move2)
def test_73_relational_inverse(self):
""" Check the consistency of relational fields with inverse(s). """
discussion1, discussion2 = self.env['test_new_api.discussion'].create([
{'name': "discussion1"}, {'name': "discussion2"},
])
category1, category2 = self.env['test_new_api.category'].create([
{'name': "category1"}, {'name': "category2"},
])
# assumption: category12 and category21 are in different order, but are
# in the same order when put in a set()
category12 = category1 + category2
category21 = category2 + category1
self.assertNotEqual(category12.ids, category21.ids)
self.assertEqual(list(set(category12.ids)), list(set(category21.ids)))
# make sure discussion1.categories is in cache; the write() below should
# update the cache of discussion1.categories by appending category12.ids
discussion1.categories
category12.write({'discussions': [Command.link(discussion1.id)]})
self.assertEqual(discussion1.categories.ids, category12.ids)
# make sure discussion2.categories is in cache; the write() below should
# update the cache of discussion2.categories by appending category21.ids
discussion2.categories
category21.write({'discussions': [Command.link(discussion2.id)]})
self.assertEqual(discussion2.categories.ids, category21.ids)
def test_80_copy(self):
Translations = self.env['ir.translation']
discussion = self.env.ref('test_new_api.discussion_0')
+1 -1
View File
@@ -3882,7 +3882,7 @@ class Many2many(_RelationalMulti):
# determine old and new relation {x: ys}
set = OrderedSet
ids = {rid for recs, cs in records_commands_list for rid in recs.ids}
ids = set(rid for recs, cs in records_commands_list for rid in recs.ids)
records = model.browse(ids)
if self.store: