fields.function stored with multi argument and mixed integer/manyone types

Bug #1018908 reported by Xavier Fernandez http://www.smile.fr
10
This bug affects 1 person
Affects Status Importance Assigned to Milestone
Odoo Server (MOVED TO GITHUB)
Fix Committed
Low
OpenERP Publisher's Warranty Team

Bug Description

This is quite a tricky bug that requires 2 fields.function stored in database, linked with a 'multi' argument and of two different types: integer and many2one. Something like that:

_columns = {
  'm2o_field_id': fields.function(_get_infos, method=True, type='many2one', relation='some.object', string='some string', store=True),
  'integer_field': fields.function(_get_infos, method=True, type='integer', string='some other string', store=True),
}

Lets say, _store_set_values(self, cr, uid, ids, fields, context):" is called with fields= ['m2o_field_id', 'integer_field'], ids = [my_id]

in orm.py, line 3824, you have:

        todo = {}
        keys = []
        for f in fields:
            if self._columns[f]._multi not in keys:
                keys.append(self._columns[f]._multi)
            todo.setdefault(self._columns[f]._multi, [])
            todo[self._columns[f]._multi].append(f)
        for key in keys:
            val = todo[key]
            if key:
                # uid == 1 for accessing objects having rules defined on store fields
                result = self._columns[val[0]].get(cr, self, ids, val, 1, context=context)

so val will contain either ['m2o_field_id', 'integer_field'] or ['integer_field', 'm2o_field_id'] depending on the order they are called

and the fields.get function will be called with val[0] which is either an integer field or a many2one field.

Now if you go to the get function of fields.function, you have this type of code:
fields.py, line 817
        if self._type == "many2one" :
            # Filtering only integer/long values if passed
            res_ids = [x for x in res.values() if x and isinstance(x, (int,long))]

            if res_ids:
                obj_model = obj.pool.get(self._obj)
                dict_names = dict(obj_model.name_get(cr, user, res_ids, context))
                for r in res.keys():
                    if res[r] and res[r] in dict_names:
                        res[r] = (res[r], dict_names[res[r]])

        if self._type == "integer":
            for r in res.keys():
                # Converting value into string so that it does not affect XML-RPC Limits
                if isinstance(res[r],dict): # To treat integer values with _multi attribute
                    for record in res[r].keys():
                        res[r][record] = str(res[r][record])
                else:
                    res[r] = str(res[r])

Either way, the function _get_infos will return something like that:
{my_id:{
'integer_field': 200,
'm2o_field_id': 42,
}}
but the result in _store_set_values will have either (depending on the order):
- if val[0] is a many2one:
result ={my_id:{
'integer_field': 200,
'm2o_field_id': 42,
}} (no_action)
or
- if val[0] is an integer:
result ={my_id:{
'integer_field': '200',
'm2o_field_id': '42',
}} (integer field transforms into string)

And in _store_set_values, you have:
in orm.py, line 3834

for id, value in result.items():
#some code
    for v in value:
        if v not in val:
            continue
        if self._columns[v]._type in ('many2one', 'one2one'):
            try:
                value[v] = value[v][0]
            except:
                pass

So we will store either:
{
'integer_field': 200,
'm2o_field_id': 42,
} => OK
or
{
'integer_field': '200',
'm2o_field_id': '4', #instead of 42
} => KO

depending on the order...

server 6.0, revno 3626

Tags: maintenance

Related branches

description: updated
Changed in openobject-server:
assignee: nobody → OpenERP Publisher's Warranty Team (openerp-opw)
tags: added: maintenance
Revision history for this message
Olivier Dony (Odoo) (odo-openerp) wrote :

When mixing different types of fields.function with the same `multi` value, the post-processing steps of one of the fields types may be inadvertently applied to the values of the other fields. This is a rare occurrence, as `multi` is mostly used to combine function.fields of the same type.
This issue does not exist in 6.1+, as fields.function.get() was refactored and corrected for 6.1.

Changed in openobject-server:
importance: Undecided → Low
milestone: none → 6.0.4
status: New → In Progress
Revision history for this message
Olivier Dony (Odoo) (odo-openerp) wrote :

This patch (untested) should fix the issue, by backporting partially the 6.1 refactoring.

Revision history for this message
Rifakat Husen (OpenERP) (rha-openerp) wrote :

I have applied above patch into below branch,
lp:~openerp-dev/openobject-server/6.0-opw-578249-rha
Revision ID: <email address hidden>
Revision 3636

Thanks!

Changed in openobject-server:
status: In Progress → Fix Committed
To post a comment you must log in.
This report contains Public information  
Everyone can see this information.

Other bug subscribers

Remote bug watches

Bug watches keep track of this bug in other bug trackers.