models inheriting by prototype (_inherit with different _name) do not get updated when parent model is modified

Bug #799378 reported by Lorenzo Battistini on 2011-06-19
46
This bug affects 5 people
Affects Status Importance Assigned to Milestone
Odoo Server (MOVED TO GITHUB)
Confirmed
Low
OpenERP's Framework R&D

Bug Description

Workarounds
===========

- In all cases, forcing a manual module update of the module in which the error occurs will take care of the error permanently. For example the error can occur if you install `base_contact` after installing `crm`. As the error message pops up when you are trying to use crm leads, forcing a manual update of the `crm` module will fix the error (by creating the missing columns)

- If the error happens in a custom module, you could also avoid it by making an explicit dependency on the other module that is causing the error to happen. In the previous example, the error would be avoided if `crm` had an explicit dependency on `base_contact`, because base_contact would always be installed and loaded *before* `crm`.

Original Description
====================

openobject-server/6.0 revno 3445

Steps:

1 - Install 'crm' module
2 - Make a module that adds a field to 'res.partner.address' (for instance, you can use 'base_partner_surname' http://apps.openerp.com/addon/1526 or 'l10n_it_base' http://apps.openerp.com/addon/4528) and install it
3 - Try to create a new lead

you get:

[2011-06-19 14:16:01,056][test] ERROR:db.cursor:Programming error: column crm_lead.last_name does not exist
LINE 1: SELECT crm_lead.date_closed,crm_lead.last_name,date_trunc('s...
                                    ^
, in query SELECT crm_lead.date_closed,crm_lead.last_name,date_trunc('second', crm_lead.create_date) as create_date,crm_lead.probability,crm_lead.type_id,crm_lead.partner_address_id,crm_lead.date_action_last,crm_lead.day_close,crm_lead.street,crm_lead.day_open,crm_lead.contact_name,crm_lead.partner_id,crm_lead.date_action_next,crm_lead.city,crm_lead.first_name,crm_lead.user_id,crm_lead.zip,crm_lead.title,crm_lead.partner_name,crm_lead.planned_revenue,crm_lead.country_id,crm_lead.company_id,crm_lead.id,crm_lead.priority,crm_lead.state,crm_lead.email_cc,crm_lead.type,crm_lead.email,crm_lead.function,crm_lead.fax,crm_lead.optin,crm_lead.description,crm_lead.street2,crm_lead.ref2,crm_lead.section_id,crm_lead.title_action,crm_lead.phone,date_trunc('second', crm_lead.write_date) as write_date,crm_lead.active,crm_lead.date_action,crm_lead.categ_id,crm_lead.name,crm_lead.stage_id,crm_lead.date_open,crm_lead.date_deadline,crm_lead.optout,crm_lead.mobile,crm_lead.ref,crm_lead.birthdate,crm_lead.channel_id,crm_lead.state_id,crm_lead.email_from,crm_lead.referred,crm_lead.id FROM "crm_lead" WHERE crm_lead.id IN %s ORDER BY priority,date_action,id desc
[2011-06-19 14:16:01,057][test] ERROR:web-services:Uncaught exception
Traceback (most recent call last):
  File "/home/elbati/workspace/openerp/openerp6/server/bin/osv/osv.py", line 122, in wrapper
    return f(self, dbname, *args, **kwargs)
  File "/home/elbati/workspace/openerp/openerp6/server/bin/osv/osv.py", line 176, in execute
    res = self.execute_cr(cr, uid, obj, method, *args, **kw)
  File "/home/elbati/workspace/openerp/openerp6/server/bin/osv/osv.py", line 167, in execute_cr
    return getattr(object, method)(cr, uid, *args, **kw)
  File "/home/elbati/workspace/openerp/openerp6/server/bin/osv/orm.py", line 3694, in create
    self.pool.get(object)._store_set_values(cr, user, ids, fields2, context)
  File "/home/elbati/workspace/openerp/openerp6/server/bin/osv/orm.py", line 3788, in _store_set_values
    result = self._columns[val[0]].get(cr, self, ids, val, 1, context=context)
  File "/home/elbati/workspace/openerp/openerp6/server/bin/osv/fields.py", line 800, in get
    res = self._fnct(obj, cr, user, ids, name, self._arg, context)
  File "/home/elbati/workspace/openerp/openerp6/server/bin/addons/crm/crm_lead.py", line 69, in _compute_day
    if lead.date_closed:
  File "/home/elbati/workspace/openerp/openerp6/server/bin/osv/orm.py", line 292, in __getattr__
    return self[name]
  File "/home/elbati/workspace/openerp/openerp6/server/bin/osv/orm.py", line 194, in __getitem__
    fields_to_fetch = filter(lambda x: x[1]._classic_write, self._table._columns.items())
  File "/home/elbati/workspace/openerp/openerp6/server/bin/osv/orm.py", line 2942, in read
    result = self._read_flat(cr, user, select, fields, context, load)
  File "/home/elbati/workspace/openerp/openerp6/server/bin/osv/orm.py", line 3001, in _read_flat
    cr.execute(query, (tuple(sub_ids),))
  File "/home/elbati/workspace/openerp/openerp6/server/bin/sql_db.py", line 78, in wrapper
    return f(self, *args, **kwargs)
  File "/home/elbati/workspace/openerp/openerp6/server/bin/sql_db.py", line 131, in execute
    res = self._obj.execute(query, params)
ProgrammingError: column crm_lead.last_name does not exist
LINE 1: SELECT crm_lead.date_closed,crm_lead.last_name,date_trunc('s...
                                    ^

This is because 'crm.lead' inherits 'res.partner.address' by prototyping, but the new module (base_partner_surname) has been installed after 'crm', so, when 'crm' was installed, 'last_name' didn't exist.

Investigating, I noticed that at line 194
http://bazaar.launchpad.net/~openerp/openobject-server/6.0/view/3445/bin/osv/orm.py#L190
'self._table._columns' contains 'last_name' while that column, as mentioned above, is not present within the database.

Hello Lorenzo,

I have checked your issue but did not face any problem like this bug description.
would you please check this with respect of addons module only and provide me the proper test case which raises the same traceback.

Thanks and waiting for your reply.

Changed in openobject-server:
status: New → Incomplete
Lorenzo Battistini (elbati) wrote :

Hello Vinay,

1 - Create new db and install 'crm' module and complete the configuration wizard
2 - After that, install the attached module (there are no 'certified' modules that add field to partner address)
3 - Create a new lead

Changed in openobject-server:
status: Incomplete → New

I am confirming this issue after checking last comment.

Thanks for pointing this out.

Changed in openobject-server:
assignee: nobody → OpenERP's Framework R&D (openerp-dev-framework)
importance: Undecided → Low
status: New → Confirmed
Changed in openobject-server:
status: Confirmed → In Progress
Changed in openobject-server:
status: In Progress → Confirmed
Naresh(OpenERP) (nch-openerp) wrote :

Hello,

The issue seems to be fixed on trunk by the latest improvements landed @ 3505 <email address hidden>.

I am setting it as Fixed released !
please reopen if you think its reproducible on trunk.

Thanks,

Changed in openobject-server:
status: Confirmed → Fix Released
Vo Minh Thu (thu) wrote :

The (almost same) bug is reproducible in trunk.

The problem as described in the bug report is the following:

Base are CRM installed. CRM (specifically crm.lead) makes a copy of Base (specifically res.partner.address) _columns. Then a new module NEW is installed, which modifies Base (adding a new column in res.partner.address).

That new column is not present in database for the CRM (which is correct, because it used an unmodified Base). The problem is that the new column appears in CRM _columns. This happens because loading installed modules and installing modules is done in a single pass. And in this case CRM is loaded after the newly installed NEW module. Net effect: CRM _columns have one more column than its database column.

In trunk:

In trunk, the problem is partially solved: installed modules are loaded prior to any module to be installed. So CRM is loaded before NEW, and its _columns and database column are in sync. But there is still a problem: when restarting the server, the modules are loaded. If NEW is loaded before CRM (i.e. opposite order of the installation time), CRM will see a new column in Base. So its _columns have again a spurious column w.r.t. the database.

Workaround:

The proposed workaround before we fix this, is to add an excplicit order between modules: i.e. NEW should depends on the CRM to make sure the CRM is loaded before (and thus unaffected by) NEW.

Possible solution:

We have to discuss this more in detail at the R&D but we think to store the installation order of the installed modules so that we can later load them in the same order. Each module will see its parent modules exactly as they were at installation time (and thus keep their _columns in sync with the database).

Changed in openobject-server:
status: Fix Released → Triaged
Stéphane Bidoul (Acsone) (sbi) wrote :

Hello,

I believe I have ve encountered a variant of this issue. I was trying to add a field to res.partner.address (by creating a module and using _inherit = 'res.partner.address').

The new field was correctly created in the database, but when trying to add it to inherited views that did not work (the error was "Can't find field in the following view parts composing the view...").

When declaring my module as dependent of "crm", the problem went away.

Best regards,

-sbi

summary: - Error reading fields of an object inherited by prototyping
+ models inheriting by prototype (_inherit with different _name) do not
+ get updated when parent model is modified

I have found something very similar in v6.1RC1, using certified modules.
If you install base_contact (that changes the behaviour of res.partner.address very deeply, adding some fields like 'location_id' and changing the definition of several ones), and you install the crm module (which inherits in crm.lead from res.partner.address), you will not be allowed to create crm.leads.

After the installing of both modules, at any attempt to call create an crm.lead (from UI or loading an xml or csv data file), it will raise an SQL error on the SQL insert statement due to the field 'location_id' not found on crm_lead table ('location_id' is a field inherited by a modified res.partner.address). This makes impossible to use crm and base_contact together (both, official and certified modules!)

In my opinion, this is a high importance fault. It is difficult to image a case where a crm user will not request the base_contact features. Additionally, it seems to be a conceptual fault in the osv framework, so most probably it will cause problems on other parts of real systems, where official and private modules for sure are combined.

Can you please retest as module loading has been rewritten around revno 3505

Changed in openobject-server:
status: Triaged → Incomplete
Lorenzo Battistini (elbati) wrote :

I'm not able to reproduce this on 6.1.
Thanks

Changed in openobject-server:
status: Incomplete → Fix Released

I can reproduce this bug (not beeing able to create lead after installing base_contact) on 6.1.1, where revision 3505 http://bazaar.launchpad.net/~openerp/openobject-server/6.1/revision/3505 has clearly landed.

Is it better to submit another bug report?

I can reproduce the bug on the 6.1 release (openerp-6.1-1), as linked from main downloads page, but not on the nightly build of 6.1 (6.1-20120401-233105)

This issue is certainly not fixed, please do not change the status unless you can find a patch that specifically addresses it.
It is a complicated issue inherent to the OpenERP module dependency system and the inheritance mechanism, and it will not be fixed by chance.
If you cannot reproduce it with the simple test case of installing the base_contact module after the crm module, it's only because the installation procedure is slightly different in 6.1, as Thu explained in comment #5. The issue will appear nevertheless as soon as the server is restarted, and as long as the base_contact module is loaded before the crm module ( you can see the loading order in the server log).

BTW the workaround is very simple: either force a dependency between the conflicting modules, e.g. make crm depend on base_contact, or even simpler, manually force an update of the module in which the error occurs (in this case crm), and it will permanently solve the issue.

PS: Independently of this bug, it seems many people believe base_contact to be an important and frequently needed module. This is mostly not correct, and base_contact is not needed at all to manage contacts. On a database without base_contact, the contacts are simply the partner addresses. The only case where base_contact is required is when the same contact needs to be associated with several parent companies. In most cases this is not needed, and for few odd cases where a contact belongs to multiple partners, duplicating it is fine. Avoiding to install base_contact will save you from a lot of trouble.

Changed in openobject-server:
status: Fix Released → Confirmed
description: updated
To post a comment you must log in.
This report contains Public information  Edit
Everyone can see this information.

Duplicates of this bug

Other bug subscribers