[FIX] base: restore deletion of dependencies on field removal

odoo/odoo#111651 improved and optimised triggers but dropped the
in-place cleanup of field dependencies. As a consequence, during
module uninstallation if a stored computed field is removed (because
it's part of a module being uninstalled), and one of its dependencies
is subsequently altered (e.g. it's itself removed, or written to) the
second update will break as the query trying to find out which
dependent records to update will error, either because of trying to
select / filter on a missing column, or because of trying to fetch
in a missing table.

The simplest examples of this issue are computed fields with a
dependency on `ir.model`:

- In `calendar`, `calendar.event.res_model` is a related on
  `res_model_id.model`, this prevents the removal of *any* `ir.model`
  record if it gets uninstalled.

  As a result the `calendar.attendee` and `calendar.event` tables
  don't get removed (just emptied of all their non-automatic fields),
  their records remain as well, and when the non-automatic fields get
  re-added during installation re-instating the NOT NULL constraints
  fails, breaking the uninstall/reinstall test.

- In `payment`, `payment.provider.module_state` is a related on
  `module_id.state`, this breaks *during* uninstallation, as after
  `module_uninstall` first calls `_module_data_uninstall` which
  removes the field, then it *updates the modules being uninstalled*
  (sets their state), which tries to find out which
  `payment.provider`'s `module_state` is should update, which breaks
  because the `module_id` column has been removed.

  This second one was worked around in odoo/odoo#118900, by marking
  modules as uninstalled before actually gutting them, but as it turns
  out the "actual" fix is needed anyway. So revert the workaround, and
  actually fix the issue.

closes odoo/odoo#119130

X-original-commit: 48a420efcf7c7b46416bab006003553cc9d23846
Signed-off-by: Xavier Morel (xmo) <xmo@odoo.com>
This commit is contained in:
Xavier Morel
2023-04-20 09:33:48 +02:00
parent c70a46b8bf
commit c7826675a8
2 changed files with 6 additions and 1 deletions
+1 -1
View File
@@ -483,9 +483,9 @@ class Module(models.Model):
tables, columns, constraints, etc.
"""
modules_to_remove = self.mapped('name')
self.env['ir.model.data']._module_data_uninstall(modules_to_remove)
# we deactivate prefetching to not try to read a column that has been deleted
self.with_context(prefetch_fields=False).write({'state': 'uninstalled', 'latest_version': False})
self.env['ir.model.data']._module_data_uninstall(modules_to_remove)
return True
def _remove_copied_views(self):
+5
View File
@@ -359,6 +359,11 @@ class Registry(Mapping):
def _discard_fields(self, fields: list):
""" Discard the given fields from the registry's internal data structures. """
for f in fields:
# tests usually don't reload the registry, so when they create
# custom fields those may not have the entire dependency setup, and
# may be missing from these maps
self.field_depends.pop(f, None)
# discard fields from field triggers
self.__dict__.pop('_field_triggers', None)