diff --git a/openerp/addons/base/res/res_partner.py b/openerp/addons/base/res/res_partner.py index f4a36b46b77..9c98521e86c 100644 --- a/openerp/addons/base/res/res_partner.py +++ b/openerp/addons/base/res/res_partner.py @@ -346,21 +346,35 @@ class res_partner_address(osv.osv): def name_search(self, cr, user, name, args=None, operator='ilike', context=None, limit=100): if not args: - args=[] - if not context: - context={} - if context.get('contact_display', 'contact')=='partner ' or context.get('contact_display', 'contact')=='partner_address ' : - ids = self.search(cr, user, [('partner_id',operator,name)], limit=limit, context=context) + args = [] + if context is None: + context = {} + + if not name: + ids = self.search(cr, user, args, limit=limit, context=context) + elif context.get('contact_display', 'contact') == 'partner': + ids = self.search(cr, user, [('partner_id', operator, name)] + args, limit=limit, context=context) else: - if not name: - ids = self.search(cr, user, args, limit=limit, context=context) + # first lookup zip code, as it is a common and efficient way to search on these data + ids = self.search(cr, user, [('zip', '=', name)] + args, limit=limit, context=context) + # then search on other fields: + if context.get('contact_display', 'contact') == 'partner_address': + fields = ['partner_id', 'name', 'country_id', 'city', 'street'] else: - ids = self.search(cr, user, [('zip','=',name)] + args, limit=limit, context=context) - if not ids: - ids = self.search(cr, user, [('city',operator,name)] + args, limit=limit, context=context) - if name: - ids += self.search(cr, user, [('name',operator,name)] + args, limit=limit, context=context) - ids += self.search(cr, user, [('partner_id',operator,name)] + args, limit=limit, context=context) + fields = ['name', 'country_id', 'city', 'street'] + # Here we have to search the records that satisfy the domain: + # OR([[(f, operator, name)] for f in fields])) + args + # Searching on such a domain can be dramatically inefficient, due to the expansion made + # for field translations, and the handling of the disjunction by the DB engine itself. + # So instead, we search field by field until the search limit is reached. + while len(ids) < limit and fields: + f = fields.pop(0) + new_ids = self.search(cr, user, [(f, operator, name)] + args, limit=limit, context=context) + # extend ids with the ones in new_ids that are not in ids yet (and keep order) + old_ids = set(ids) + ids.extend([id for id in new_ids if id not in old_ids]) + + ids = ids[:limit] return self.name_get(cr, user, ids, context=context) def get_city(self, cr, uid, id):