From 78a20a3dba07762d2de1e22072c20be1bc59d20f Mon Sep 17 00:00:00 2001 From: Raphael Collet Date: Tue, 12 May 2015 10:29:46 +0200 Subject: [PATCH] [FIX] model: wrong alias used in read query for multi-inherited field In commit 04ba0e99, we introduced an optimization for reading inherited fields in a single query. There is an issue when you have more than one level of `_inherits`. The query looks like: SELECT ... FROM table0, table1 AS alias1, table2 AS alias2 WHERE table0.link0 = alias1.id AND table1.link1 = alias2.id AND ... ^^^^^^ should be alias1 This fixes the issue, and adds a test to reproduce it. The fix is based on @emiprotechnologies's own proposal, but is cleaner and does not break APIs. --- .../test_inherits/tests/test_inherits.py | 5 +++++ openerp/models.py | 22 ++++++++++++------- 2 files changed, 19 insertions(+), 8 deletions(-) diff --git a/openerp/addons/test_inherits/tests/test_inherits.py b/openerp/addons/test_inherits/tests/test_inherits.py index 7ff5dee814b..d45882b5258 100644 --- a/openerp/addons/test_inherits/tests/test_inherits.py +++ b/openerp/addons/test_inherits/tests/test_inherits.py @@ -16,6 +16,11 @@ class test_inherits(common.TransactionCase): self.assertEqual(pallet.field_in_box, 'box') self.assertEqual(pallet.field_in_pallet, 'pallet') + def test_read_3_levels_inherits(self): + """ Check that we can read an inherited field on 3 levels """ + pallet = self.env.ref('test_inherits.pallet_a') + self.assertEqual(pallet.read(['name']), [{'id': pallet.id, 'name': 'Unit A'}]) + def test_write_3_levels_inherits(self): """ Check that we can create an inherits on 3 levels """ pallet = self.env.ref('test_inherits.pallet_a') diff --git a/openerp/models.py b/openerp/models.py index 858993f94d4..5c19f253b71 100644 --- a/openerp/models.py +++ b/openerp/models.py @@ -2184,14 +2184,20 @@ class BaseModel(object): :param query: query object on which the JOIN should be added :return: qualified name of field, to be used in SELECT clause """ - current_table = self - parent_alias = '"%s"' % current_table._table - while field in current_table._inherit_fields and not field in current_table._columns: - parent_model_name = current_table._inherit_fields[field][0] - parent_table = self.pool[parent_model_name] - parent_alias = self._inherits_join_add(current_table, parent_model_name, query) - current_table = parent_table - return '%s."%s"' % (parent_alias, field) + # INVARIANT: alias is the SQL alias of model._table in query + model, alias = self, self._table + while field in model._inherit_fields and field not in model._columns: + # retrieve the parent model where field is inherited from + parent_model_name = model._inherit_fields[field][0] + parent_model = self.pool[parent_model_name] + parent_field = model._inherits[parent_model_name] + # JOIN parent_model._table AS parent_alias ON alias.parent_field = parent_alias.id + parent_alias, _ = query.add_join( + (alias, parent_model._table, parent_field, 'id', parent_field), + implicit=True, + ) + model, alias = parent_model, parent_alias + return '"%s"."%s"' % (alias, field) def _parent_store_compute(self, cr): if not self._parent_store: