[FIX]:_inherits for multilevel inheritence

lp bug: https://launchpad.net/bugs/823691 fixed

bzr revid: nch@tinyerp.com-20110826103516-o220jqwqdr3uwjhn
This commit is contained in:
Naresh (OpenERP) 2011-08-26 16:05:16 +05:30
parent eba378a4d6
commit 8d0cf999ac
2 changed files with 35 additions and 29 deletions

View File

@ -53,7 +53,7 @@ def _symbol_set(symb):
class _column(object): class _column(object):
""" Base of all fields, a database column """ Base of all fields, a database column
An instance of this object is a *description* of a database column. It will An instance of this object is a *description* of a database column. It will
not hold any data, but only provide the methods to manipulate data of an not hold any data, but only provide the methods to manipulate data of an
ORM record or even prepare/update the database to hold such a field of data. ORM record or even prepare/update the database to hold such a field of data.
@ -1285,7 +1285,7 @@ class property(function):
def _fnct_read(self, obj, cr, uid, ids, prop_names, obj_dest, context=None): def _fnct_read(self, obj, cr, uid, ids, prop_names, obj_dest, context=None):
prop = obj.pool.get('ir.property') prop = obj.pool.get('ir.property')
# get the default values (for res_id = False) for the property fields # get the default values (for res_id = False) for the property fields
default_val = self._get_defaults(obj, cr, uid, prop_names, context) default_val = self._get_defaults(obj, cr, uid, prop_names, context)
# build the dictionary that will be returned # build the dictionary that will be returned
@ -1407,12 +1407,16 @@ class column_info(object):
:attr parent_column: the name of the column containing the m2o :attr parent_column: the name of the column containing the m2o
relationship to the parent model that contains relationship to the parent model that contains
this column, None for local columns. this column, None for local columns.
:attr original_parent: if the column is inherited, name of the original
parent model that contains it i.e in case of multilevel
inheritence, None for local columns.
""" """
def __init__(self, name, column, parent_model=None, parent_column=None): def __init__(self, name, column, parent_model=None, parent_column=None, original_parent=None):
self.name = name self.name = name
self.column = column self.column = column
self.parent_model = parent_model self.parent_model = parent_model
self.parent_column = parent_column self.parent_column = parent_column
self.original_parent = original_parent
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -38,7 +38,7 @@
- classicals (varchar, integer, boolean, ...) - classicals (varchar, integer, boolean, ...)
- relations (one2many, many2one, many2many) - relations (one2many, many2one, many2many)
- functions - functions
""" """
import calendar import calendar
@ -168,7 +168,7 @@ def modifiers_tests():
test_modifiers({}, '{}') test_modifiers({}, '{}')
test_modifiers({"invisible": True}, '{"invisible": true}') test_modifiers({"invisible": True}, '{"invisible": true}')
test_modifiers({"invisible": False}, '{}') test_modifiers({"invisible": False}, '{}')
def check_object_name(name): def check_object_name(name):
""" Check if the given name is a valid openerp object name. """ Check if the given name is a valid openerp object name.
@ -255,7 +255,7 @@ class browse_null(object):
# #
class browse_record_list(list): class browse_record_list(list):
""" Collection of browse objects """ Collection of browse objects
Such an instance will be returned when doing a ``browse([ids..])`` Such an instance will be returned when doing a ``browse([ids..])``
and will be iterable, yielding browse() objects and will be iterable, yielding browse() objects
""" """
@ -270,9 +270,9 @@ class browse_record_list(list):
class browse_record(object): class browse_record(object):
""" An object that behaves like a row of an object's table. """ An object that behaves like a row of an object's table.
It has attributes after the columns of the corresponding object. It has attributes after the columns of the corresponding object.
Examples:: Examples::
uobj = pool.get('res.users') uobj = pool.get('res.users')
user_rec = uobj.browse(cr, uid, 104) user_rec = uobj.browse(cr, uid, 104)
name = user_rec.name name = user_rec.name
@ -1093,7 +1093,7 @@ class orm_template(object):
if line[i] and skip: if line[i] and skip:
return False return False
continue continue
#set the mode for m2o, o2m, m2m : xml_id/id/name #set the mode for m2o, o2m, m2m : xml_id/id/name
if len(field) == len(prefix)+1: if len(field) == len(prefix)+1:
mode = False mode = False
@ -1106,7 +1106,7 @@ class orm_template(object):
for db_id in line.split(config.get('csv_internal_sep')): for db_id in line.split(config.get('csv_internal_sep')):
res.append(_get_id(relation, db_id, current_module, mode)) res.append(_get_id(relation, db_id, current_module, mode))
return [(6,0,res)] return [(6,0,res)]
# ID of the record using a XML ID # ID of the record using a XML ID
if field[len(prefix)]=='id': if field[len(prefix)]=='id':
try: try:
@ -1130,9 +1130,9 @@ class orm_template(object):
relation_obj = self.pool.get(relation) relation_obj = self.pool.get(relation)
newfd = relation_obj.fields_get( cr, uid, context=context ) newfd = relation_obj.fields_get( cr, uid, context=context )
pos = position pos = position
res = many_ids(line[i], relation, current_module, mode) res = many_ids(line[i], relation, current_module, mode)
first = 0 first = 0
while pos < len(datas): while pos < len(datas):
res2 = process_liness(self, datas, prefix + [field[len(prefix)]], current_module, relation_obj._name, newfd, pos, first) res2 = process_liness(self, datas, prefix + [field[len(prefix)]], current_module, relation_obj._name, newfd, pos, first)
@ -1142,15 +1142,15 @@ class orm_template(object):
nbrmax = max(nbrmax, pos) nbrmax = max(nbrmax, pos)
warning += w2 warning += w2
first += 1 first += 1
if data_res_id2: if data_res_id2:
res.append((4, data_res_id2)) res.append((4, data_res_id2))
if (not newrow) or not reduce(lambda x, y: x or y, newrow.values(), 0): if (not newrow) or not reduce(lambda x, y: x or y, newrow.values(), 0):
break break
res.append( (data_res_id2 and 1 or 0, data_res_id2 or 0, newrow) ) res.append( (data_res_id2 and 1 or 0, data_res_id2 or 0, newrow) )
elif fields_def[field[len(prefix)]]['type']=='many2one': elif fields_def[field[len(prefix)]]['type']=='many2one':
relation = fields_def[field[len(prefix)]]['relation'] relation = fields_def[field[len(prefix)]]['relation']
@ -1179,7 +1179,7 @@ class orm_template(object):
else: else:
res = line[i] res = line[i]
row[field[len(prefix)]] = res or False row[field[len(prefix)]] = res or False
result = (row, nbrmax, warning, data_res_id, xml_id) result = (row, nbrmax, warning, data_res_id, xml_id)
@ -1193,7 +1193,7 @@ class orm_template(object):
position = 0 position = 0
while position<len(datas): while position<len(datas):
res = {} res = {}
(res, position, warning, res_id, xml_id) = \ (res, position, warning, res_id, xml_id) = \
process_liness(self, datas, [], current_module, self._name, fields_def, position=position) process_liness(self, datas, [], current_module, self._name, fields_def, position=position)
if len(warning): if len(warning):
@ -1560,7 +1560,7 @@ class orm_template(object):
field = model_fields.get(node.get('name')) field = model_fields.get(node.get('name'))
if field: if field:
transfer_field_to_modifiers(field, modifiers) transfer_field_to_modifiers(field, modifiers)
elif node.tag in ('form', 'tree'): elif node.tag in ('form', 'tree'):
result = self.view_header_get(cr, user, False, node.tag, context) result = self.view_header_get(cr, user, False, node.tag, context)
@ -2609,20 +2609,22 @@ class orm(orm_template):
del d['id'] del d['id']
return data return data
def _inherits_join_add(self, parent_model_name, query): def _inherits_join_add(self, current_table, parent_model_name, query):
""" """
Add missing table SELECT and JOIN clause to ``query`` for reaching the parent table (no duplicates) Add missing table SELECT and JOIN clause to ``query`` for reaching the parent table (no duplicates)
:param current_table: current model object
:param parent_model_name: name of the parent model for which the clauses should be added :param parent_model_name: name of the parent model for which the clauses should be added
:param query: query object on which the JOIN should be added :param query: query object on which the JOIN should be added
""" """
inherits_field = self._inherits[parent_model_name] inherits_field = current_table._inherits[parent_model_name]
parent_model = self.pool.get(parent_model_name) parent_model = self.pool.get(parent_model_name)
parent_table_name = parent_model._table parent_table_name = parent_model._table
quoted_parent_table_name = '"%s"' % parent_table_name quoted_parent_table_name = '"%s"' % parent_table_name
if quoted_parent_table_name not in query.tables: if quoted_parent_table_name not in query.tables:
query.tables.append(quoted_parent_table_name) query.tables.append(quoted_parent_table_name)
query.where_clause.append('("%s".%s = %s.id)' % (self._table, inherits_field, parent_table_name)) query.where_clause.append('(%s.%s = %s.id)' % (current_table._table, inherits_field, parent_table_name))
def _inherits_join_calc(self, field, query): def _inherits_join_calc(self, field, query):
""" """
@ -2637,7 +2639,7 @@ class orm(orm_template):
while field in current_table._inherit_fields and not field in current_table._columns: while field in current_table._inherit_fields and not field in current_table._columns:
parent_model_name = current_table._inherit_fields[field][0] parent_model_name = current_table._inherit_fields[field][0]
parent_table = self.pool.get(parent_model_name) parent_table = self.pool.get(parent_model_name)
self._inherits_join_add(parent_model_name, query) self._inherits_join_add(current_table, parent_model_name, query)
current_table = parent_table current_table = parent_table
return '"%s".%s' % (current_table._table, field) return '"%s".%s' % (current_table._table, field)
@ -3328,9 +3330,9 @@ class orm(orm_template):
for table in self._inherits: for table in self._inherits:
other = self.pool.get(table) other = self.pool.get(table)
for col in other._columns.keys(): for col in other._columns.keys():
res[col] = (table, self._inherits[table], other._columns[col]) res[col] = (table, self._inherits[table], other._columns[col], table)
for col in other._inherit_fields.keys(): for col in other._inherit_fields.keys():
res[col] = (table, self._inherits[table], other._inherit_fields[col][2]) res[col] = (table, self._inherits[table], other._inherit_fields[col][2], other._inherit_fields[col][3])
self._inherit_fields = res self._inherit_fields = res
self._all_columns = self._get_column_infos() self._all_columns = self._get_column_infos()
self._inherits_reload_src() self._inherits_reload_src()
@ -3341,8 +3343,8 @@ class orm(orm_template):
inherited field via _inherits) to a ``column_info`` struct inherited field via _inherits) to a ``column_info`` struct
giving detailed columns """ giving detailed columns """
result = {} result = {}
for k, (parent, m2o, col) in self._inherit_fields.iteritems(): for k, (parent, m2o, col, original_parent) in self._inherit_fields.iteritems():
result[k] = fields.column_info(k, col, parent, m2o) result[k] = fields.column_info(k, col, parent, m2o, original_parent)
for k, col in self._columns.iteritems(): for k, col in self._columns.iteritems():
result[k] = fields.column_info(k, col) result[k] = fields.column_info(k, col)
return result return result
@ -4373,7 +4375,7 @@ class orm(orm_template):
if parent_model and child_object: if parent_model and child_object:
# as inherited rules are being applied, we need to add the missing JOIN # as inherited rules are being applied, we need to add the missing JOIN
# to reach the parent table (if it was not JOINed yet in the query) # to reach the parent table (if it was not JOINed yet in the query)
child_object._inherits_join_add(parent_model, query) child_object._inherits_join_add(child_object, parent_model, query)
query.where_clause += added_clause query.where_clause += added_clause
query.where_clause_params += added_params query.where_clause_params += added_params
for table in added_tables: for table in added_tables:
@ -4462,7 +4464,7 @@ class orm(orm_template):
else: else:
continue # ignore non-readable or "non-joinable" fields continue # ignore non-readable or "non-joinable" fields
elif order_field in self._inherit_fields: elif order_field in self._inherit_fields:
parent_obj = self.pool.get(self._inherit_fields[order_field][0]) parent_obj = self.pool.get(self._inherit_fields[order_field][3])
order_column = parent_obj._columns[order_field] order_column = parent_obj._columns[order_field]
if order_column._classic_read: if order_column._classic_read:
inner_clause = self._inherits_join_calc(order_field, query) inner_clause = self._inherits_join_calc(order_field, query)