Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions src/base/tests/test_util.py
Original file line number Diff line number Diff line change
Expand Up @@ -1942,6 +1942,24 @@ def test_delete_unused_multi_cascade_fk(self):
self.assertTrue(cat_2.exists())
self.assertTrue(cat_3.exists())

def test_delete_unused_include_m2m(self):
cat_1, cat_2, cat_3 = self._prepare_test_delete_unused()

cr = self.env.cr
cr.execute(
"INSERT INTO res_partner_res_partner_category_rel(partner_id, category_id) VALUES(%s, %s)",
[util.ref(cr, "base.partner_root"), cat_2.id],
)

deleted = util.delete_unused(
self.env.cr, f"base.{cat_1.name}", f"base.{cat_2.name}", f"base.{cat_3.name}", include_m2m="*"
)

self.assertEqual(deleted, [f"base.{cat_3.name}"])
self.assertTrue(cat_1.exists())
self.assertTrue(cat_2.exists())
self.assertFalse(cat_3.exists())


class TestEditView(UnitTestCase):
@parametrize(
Expand Down
8 changes: 7 additions & 1 deletion src/util/records.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
format_query,
get_columns,
get_fk,
get_m2m_tables,
get_value_or_en_translation,
parallel_execute,
table_exists,
Expand Down Expand Up @@ -1282,11 +1283,14 @@ def delete_unused(cr, *xmlids, **kwargs):
:param bool keep_xmlids: whether to keep the xml_ids of records that cannot be
removed. By default `True` for versions up to 18.0,
`False` from `saas~18.1` on.
:param list(str) or str include_m2m: list of m2m tables to include in the search.
`"*"` for all.
:return: list of ids of removed records, if any
:rtype: list(int)
"""
deactivate = kwargs.pop("deactivate", False)
keep_xmlids = kwargs.pop("keep_xmlids", not version_gte("saas~18.1"))
include_m2m = kwargs.pop("include_m2m", ())
if kwargs:
raise TypeError("delete_unused() got an unexpected keyword argument %r" % kwargs.popitem()[0])

Expand Down Expand Up @@ -1358,12 +1362,14 @@ def delete_unused(cr, *xmlids, **kwargs):
else:
kids_query = format_query(cr, "SELECT id, ARRAY[id] AS children FROM {0} WHERE id = ANY(%(ids)s)", table)

m2m_tables = include_m2m if include_m2m != "*" else get_m2m_tables(cr, table)

sub = " UNION ALL ".join(
[
format_query(cr, "SELECT 1 FROM {} x WHERE x.{} = ANY(s.children)", fk_tbl, fk_col)
for fk_tbl, fk_col, _, fk_act in get_fk(cr, table, quote_ident=False)
# ignore "on delete cascade" fk (they are indirect dependencies (lines or m2m))
if fk_act != "c"
if (fk_act != "c" or fk_tbl in m2m_tables)
# ignore children records unless the deletion is restricted
if not (fk_tbl == table and fk_act != "r")
]
Expand Down