Skip to content
Browse files

[FIX] base: proper removal of xmlid after update

This commit fixes several bugs:

1. if a module A does the following

class Foo(models.Model):
    _inherit = 'res.partner'

    def copy(self, default=None):

a new 'A.model_res_partner' is created

If the override is removed (code change, migration,...), after an update of the
module A the A.model_res_partner should be removed (but not the
model res.partner obviously, cf 91882dd)

This was not the case as A.model_res_partner had noupdate='NULL' instead of
'false' (not specified in the query).
Bug introduced at 004a0b9

Changing to '!= true' to match only the one explicitly in noupdate

2. properly populate the self.pool.loaded_xmlids

All module external ids _must_ be present in loaded_xmlids otherwise will be
removed after a module update.

The entries created through _reflect_model were not loaded in self.loaded_xmlids
if the != true clause was merged alone, all the models defined in a module would
be tested for removal, even if the code is still present

cf opw-1962321

The categories were generated when the db was initalised, doing SQL was not
Create the categories in noupdate to avoid it being deleted.
Are always created in noupdate in data files but in stock_account it was
manually created without being in noupdate

Co-authored-by: Raphael Collet <>
  • Loading branch information...
mart-e and rco-odoo committed Apr 23, 2019
1 parent 9378552 commit 35c4dc37fe85e148c8dd45f5a9b7b94a7e32f156
Showing with 7 additions and 13 deletions.
  1. +1 −1 addons/stock_account/
  2. +4 −10 odoo/addons/base/models/
  3. +2 −2 odoo/modules/
@@ -91,4 +91,4 @@ def _configure_journals(cr, registry):
'value': 'account.account,'+str(account_id),
'company_id': env.ref('base.main_company').id,
env['']._load_records([dict(xml_id=xml_id, values=vals)])
env['']._load_records([dict(xml_id=xml_id, values=vals, noupdate=True)])
@@ -280,14 +280,8 @@ def _reflect_model(self, model):

if model._module == self._context.get('module'):
# self._module is the name of the module that last extended self
xmlid = 'model_' + model._name.replace('.', '_')
cr.execute("SELECT * FROM ir_model_data WHERE name=%s AND module=%s",
(xmlid, self._context['module']))
if not cr.rowcount:
cr.execute(""" INSERT INTO ir_model_data (module, name, model, res_id, date_init, date_update)
VALUES (%s, %s, %s, %s, (now() at time zone 'UTC'), (now() at time zone 'UTC')) """,
(self._context['module'], xmlid, record._name,

xmlid = '%s.model_%s' % (model._module, model._name.replace('.', '_'))
self.env['']._update_xmlids([{'xml_id': xmlid, 'record': record}])
return record

@@ -1646,9 +1640,9 @@ def _process_end(self, modules):
loaded_xmlids = self.pool.loaded_xmlids

query = """ SELECT id, module || '.' || name, model, res_id FROM ir_model_data
WHERE module IN %s AND res_id IS NOT NULL AND noupdate=%s ORDER BY id DESC
WHERE module IN %s AND res_id IS NOT NULL AND COALESCE(noupdate, false) != %s ORDER BY id DESC
self._cr.execute(query, (tuple(modules), False))
self._cr.execute(query, (tuple(modules), True))
for (id, xmlid, model, res_id) in self._cr.fetchall():
if xmlid not in loaded_xmlids:
if model in self.env:
@@ -105,8 +105,8 @@ def create_categories(cr, categories):
(name, parent_id) \
VALUES (%s, %s) RETURNING id', (categories[0], p_id))
c_id = cr.fetchone()[0]
cr.execute('INSERT INTO ir_model_data (module, name, res_id, model) \
VALUES (%s, %s, %s, %s)', ('base', xml_id, c_id, 'ir.module.category'))
cr.execute('INSERT INTO ir_model_data (module, name, res_id, model, noupdate) \
VALUES (%s, %s, %s, %s, %s)', ('base', xml_id, c_id, 'ir.module.category', True))
c_id = c_id[0]
p_id = c_id

0 comments on commit 35c4dc3

Please sign in to comment.
You can’t perform that action at this time.