odoo/odoo#72802

Created by Adrian Torres (adt)
Merged at 6d37a46d7b00d7b12e5d40dc33feeeb14655f48c

Statuses:

label
odoo-dev:13.0-fix-crm-uninstall-adt
head
badf00daf177465116b2718a030f823df3473126
merged
4 years ago by Adrian Torres (adt)
odoo/odoo
13.0 #72802
14.0 #73523
saas-14.3 #73665
saas-14.4 #73666
15.0
16.0
17.0
18.0
saas-18.2
saas-18.3
saas-18.4
master #73668

[FIX] base: perform sanity check on undeletable ir.model.data

This commit adds a sanity check to the part of the ORM that uninstalls
module data, as a recap, here's how module uninstallation works:

  • We fetch all data (ir.model.data) that corresponds to the module being
    uninstalled (WHERE module='my_module')
  • We divide this data according to its type (ir.model, ir.model.field,
    constraints, etc.)
  • We fetch the corresponding records to each type, we delete them in a
    certain order (e.g. ir.model.field before ir.model) and then finally we
    delete the ir.model.data as a last step

The data is deleted in batch for maximum performance, if one of the data
cannot be deleted however, we perform a binary search until we find the
culprit(s) and we store these culprits in a list of undeletable_ids.

At the end of the process, we delete all ir.model.data except for
the ones that are undeletable, however, it is possible that because of
the multiple-step procedure, an undeletable ir.model.data could have
become deletable.

Imagine that an ir.model.field cannot be deleted, its module data id is
added to the list of undeletable_ids, however if later on its ir.model
is deleted successfully, the ir.model.field is dropped because its table
is dropped, in this case the ir.model.data becomes deletable, but since
we simply ignore it at the end of the process, we potentially end up
with orphaned xmlids.

This can be problematic when we reinstall the module and uninstall it
again, as the system does not expect an orphaned xmlid, will completely
crash and prevent the 2nd uninstallation of the module.

This is the case with CRM and its
crm.lead.scoring.frequency.field.field_id field, its ir.model.field
cannot be deleted because the name field (and display_name) of the same
model depend on it, so it is left as is, then further down the process
the entire model is deleted and as a result so is all of its remaining
fields, however the ir.module.data for the field that could not be
deleted remains.

opw-2575592