diff --git a/odoo/addons/base/tests/test_expression.py b/odoo/addons/base/tests/test_expression.py index 28acdb0d4f7..80b391b40ec 100644 --- a/odoo/addons/base/tests/test_expression.py +++ b/odoo/addons/base/tests/test_expression.py @@ -1418,21 +1418,16 @@ class TestMany2one(TransactionCase): ''']): self.Partner.search([('company_id', 'like', self.company.name)]) - with self.assertQueries([ - ''' - SELECT "res_company".id - FROM "res_company" - WHERE (("res_company"."name"::text not like %s) - OR "res_company"."name" IS NULL) - ORDER BY "res_company"."sequence" ,"res_company"."name" - ''', - ''' + with self.assertQueries([''' SELECT "res_partner".id FROM "res_partner" - WHERE (("res_partner"."company_id" IN (%s)) OR "res_partner"."company_id" IS NULL) + WHERE (("res_partner"."company_id" IN ( + SELECT "res_company".id + FROM "res_company" + WHERE (("res_company"."name"::text not like %s) OR "res_company"."name" IS NULL)) + ) OR "res_partner"."company_id" IS NULL) ORDER BY "res_partner"."display_name" - ''' - ]): + ''']): self.Partner.search([('company_id', 'not like', "blablabla")]) diff --git a/odoo/osv/expression.py b/odoo/osv/expression.py index a6861b7dcfc..2f45c5a5057 100644 --- a/odoo/osv/expression.py +++ b/odoo/osv/expression.py @@ -861,30 +861,33 @@ class expression(object): dom = HIERARCHY_FUNCS[operator]('id', ids2, model, parent=left) for dom_leaf in dom: push(dom_leaf, model, alias) - else: - def _get_expression(comodel, left, right, operator): - #Special treatment to ill-formed domains - operator = (operator in ['<', '>', '<=', '>=']) and 'in' or operator - dict_op = {'not in': '!=', 'in': '=', '=': 'in', '!=': 'not in'} - if isinstance(right, tuple): - right = list(right) - if (not isinstance(right, list)) and operator in ['not in', 'in']: - operator = dict_op[operator] - elif isinstance(right, list) and operator in ['!=', '=']: # for domain (FIELD,'=',['value1','value2']) - operator = dict_op[operator] - res_ids = comodel.with_context(active_test=False)._name_search(right, [], operator, limit=None) - if operator in NEGATIVE_TERM_OPERATORS: - res_ids = list(res_ids) + [False] # TODO this should not be appended if False was in 'right' - return left, 'in', res_ids - # resolve string-based m2o criterion into IDs - if isinstance(right, str) or \ - isinstance(right, (tuple, list)) and right and all(isinstance(item, str) for item in right): - push(_get_expression(comodel, left, right, operator), model, alias) + elif ( + isinstance(right, str) + or isinstance(right, (tuple, list)) and right and all(isinstance(item, str) for item in right) + ): + # resolve string-based m2o criterion into IDs subqueries + + # Special treatment to ill-formed domains + operator = 'in' if operator in ('<', '>', '<=', '>=') else operator + dict_op = {'not in': '!=', 'in': '=', '=': 'in', '!=': 'not in'} + if isinstance(right, tuple): + right = list(right) + if not isinstance(right, list) and operator in ('not in', 'in'): + operator = dict_op[operator] + elif isinstance(right, list) and operator in ('!=', '='): # for domain (FIELD,'=',['value1','value2']) + operator = dict_op[operator] + res_ids = comodel.with_context(active_test=False)._name_search(right, [], operator, limit=None) + if operator in NEGATIVE_TERM_OPERATORS: + for dom_leaf in ('|', (left, 'in', res_ids), (left, '=', False)): + push(dom_leaf, model, alias) else: - # right == [] or right == False and all other cases are handled by __leaf_to_sql() - expr, params = self.__leaf_to_sql(leaf, model, alias) - push_result(expr, params) + push((left, 'in', res_ids), model, alias) + + else: + # right == [] or right == False and all other cases are handled by __leaf_to_sql() + expr, params = self.__leaf_to_sql(leaf, model, alias) + push_result(expr, params) # ------------------------------------------------- # BINARY FIELDS STORED IN ATTACHMENT