diff --git a/openerp/addons/base/tests/test_expression.py b/openerp/addons/base/tests/test_expression.py index e3b94aac3b3..15f6911315e 100644 --- a/openerp/addons/base/tests/test_expression.py +++ b/openerp/addons/base/tests/test_expression.py @@ -211,8 +211,8 @@ class test_expression(common.TransactionCase): self.assertEqual(set(partner_ids), set([p_aa]), "_auto_join off: ('bank_ids.sanitized_acc_number', 'like', '..'): incorrect result") # Test produced queries - self.assertEqual(len(self.query_list), 3, - "_auto_join off: ('bank_ids.sanitized_acc_number', 'like', '..') should produce 3 queries (1 in res_partner_bank, 2 on res_partner)") + self.assertEqual(len(self.query_list), 2, + "_auto_join off: ('bank_ids.sanitized_acc_number', 'like', '..') should produce 2 queries (1 in res_partner_bank, 1 on res_partner)") sql_query = self.query_list[0].get_sql() self.assertIn('res_partner_bank', sql_query[0], "_auto_join off: ('bank_ids.sanitized_acc_number', 'like', '..') first query incorrect main table") @@ -223,13 +223,13 @@ class test_expression(common.TransactionCase): self.assertEqual(set(['%' + name_test + '%']), set(sql_query[2]), "_auto_join off: ('bank_ids.sanitized_acc_number', 'like', '..') first query incorrect parameter") - sql_query = self.query_list[2].get_sql() + sql_query = self.query_list[1].get_sql() self.assertIn('res_partner', sql_query[0], - "_auto_join off: ('bank_ids.sanitized_acc_number', 'like', '..') third query incorrect main table") + "_auto_join off: ('bank_ids.sanitized_acc_number', 'like', '..') second query incorrect main table") self.assertIn('"res_partner"."id" in (%s)', sql_query[1], - "_auto_join off: ('bank_ids.sanitized_acc_number', 'like', '..') third query incorrect where condition") + "_auto_join off: ('bank_ids.sanitized_acc_number', 'like', '..') second query incorrect where condition") self.assertEqual(set([p_aa]), set(sql_query[2]), - "_auto_join off: ('bank_ids.sanitized_acc_number', 'like', '..') third query incorrect parameter") + "_auto_join off: ('bank_ids.sanitized_acc_number', 'like', '..') second query incorrect parameter") # Do: cascaded one2many without _auto_join self._reinit_mock() @@ -238,8 +238,8 @@ class test_expression(common.TransactionCase): self.assertEqual(set(partner_ids), set([p_a, p_b]), "_auto_join off: ('child_ids.bank_ids.id', 'in', [..]): incorrect result") # Test produced queries - self.assertEqual(len(self.query_list), 5, - "_auto_join off: ('child_ids.bank_ids.id', 'in', [..]) should produce 5 queries (1 in res_partner_bank, 4 on res_partner)") + self.assertEqual(len(self.query_list), 3, + "_auto_join off: ('child_ids.bank_ids.id', 'in', [..]) should produce 3 queries (1 in res_partner_bank, 2 on res_partner)") # Do: one2many with _auto_join partner_bank_ids_col._auto_join = True @@ -470,7 +470,7 @@ class test_expression(common.TransactionCase): self.assertTrue(set([p_a, p_b]).issubset(set(partner_ids)), "_auto_join off: ('child_ids.state_id.country_id.code', 'like', '..') incorrect result") # Test produced queries - self.assertEqual(len(self.query_list), 5, + self.assertEqual(len(self.query_list), 4, "_auto_join off: ('child_ids.state_id.country_id.code', 'like', '..') number of queries incorrect") # Do: ('child_ids.state_id.country_id.code', 'like', '..') with _auto_join diff --git a/openerp/osv/expression.py b/openerp/osv/expression.py index 50c6a80b761..e97625a44bd 100644 --- a/openerp/osv/expression.py +++ b/openerp/osv/expression.py @@ -883,8 +883,7 @@ class expression(object): # Making search easier when there is a left operand as column.o2m or column.m2m elif len(path) > 1 and column and column._type in ['many2many', 'one2many']: right_ids = comodel.search(cr, uid, [(path[1], operator, right)], context=context) - table_ids = model.search(cr, uid, [(path[0], 'in', right_ids)], context=dict(context, active_test=False)) - leaf.leaf = ('id', 'in', table_ids) + leaf.leaf = (path[0], 'in', right_ids) push(leaf) elif not column: @@ -1012,15 +1011,16 @@ class expression(object): rel_table, rel_id1, rel_id2 = column._sql_names(model) if operator in HIERARCHY_FUNCS: - def _rec_convert(ids): - if comodel == model: - return ids - return select_from_where(cr, rel_id1, rel_table, rel_id2, ids, operator) - ids2 = to_ids(right, comodel, context) dom = HIERARCHY_FUNCS[operator]('id', ids2, comodel, context=context) ids2 = comodel.search(cr, uid, dom, context=context) - push(create_substitution_leaf(leaf, ('id', 'in', _rec_convert(ids2)), model)) + if comodel == model: + push(create_substitution_leaf(leaf, ('id', 'in', ids2), model)) + else: + subquery = 'SELECT "%s" FROM "%s" WHERE "%s" IN %%s' % (rel_id1, rel_table, rel_id2) + # avoid flattening of argument in to_sql() + subquery = cr.mogrify(subquery, [tuple(ids2)]) + push(create_substitution_leaf(leaf, ('id', 'inselect', (subquery, [])), internal=True)) else: call_null_m2m = True if right is not False: @@ -1046,8 +1046,11 @@ class expression(object): operator = 'in' # operator changed because ids are directly related to main object else: call_null_m2m = False - m2m_op = 'not in' if operator in NEGATIVE_TERM_OPERATORS else 'in' - push(create_substitution_leaf(leaf, ('id', m2m_op, select_from_where(cr, rel_id1, rel_table, rel_id2, res_ids, operator) or [0]), model)) + subop = 'not inselect' if operator in NEGATIVE_TERM_OPERATORS else 'inselect' + subquery = 'SELECT "%s" FROM "%s" WHERE "%s" IN %%s' % (rel_id1, rel_table, rel_id2) + # avoid flattening of argument in to_sql() + subquery = cr.mogrify(subquery, [tuple(filter(None, res_ids))]) + push(create_substitution_leaf(leaf, ('id', subop, (subquery, [])), internal=True)) if call_null_m2m: m2m_op = 'in' if operator in NEGATIVE_TERM_OPERATORS else 'not in'