[MERGE] forward port of branch 7.0 up to revid 5274 chs@openerp.com-20140404141611-qi1yagltvkd9q8ji

bzr revid: chs@openerp.com-20140404155858-mvupqmuvi8ime2tl
This commit is contained in:
Christophe Simonis 2014-04-04 17:58:58 +02:00
commit 120342d537
3 changed files with 55 additions and 28 deletions

View File

@ -28,6 +28,7 @@ import openerp
from openerp import SUPERUSER_ID
from openerp import tools
from openerp.osv import osv, fields
from openerp.osv.expression import get_unaccent_wrapper
from openerp.tools.translate import _
class format_address(object):
@ -231,7 +232,7 @@ class res_partner(osv.osv, format_address):
'display_name': fields.function(_display_name, type='char', string='Name', store=_display_name_store_triggers, select=True),
'date': fields.date('Date', select=1),
'title': fields.many2one('res.partner.title', 'Title'),
'parent_id': fields.many2one('res.partner', 'Related Company'),
'parent_id': fields.many2one('res.partner', 'Related Company', select=True),
'child_ids': fields.one2many('res.partner', 'parent_id', 'Contacts', domain=[('active','=',True)]), # force "active_test" domain to bypass _search() override
'ref': fields.char('Reference', size=64, select=1),
'lang': fields.selection(_lang_get, 'Language',
@ -629,10 +630,17 @@ class res_partner(osv.osv, format_address):
if operator in ('=ilike', '=like'):
operator = operator[1:]
query = ('SELECT id FROM res_partner ' +
where_str + '(email ' + operator + ''' %s
OR display_name ''' + operator + ''' %s)
ORDER BY display_name''')
unaccent = get_unaccent_wrapper(cr)
query = """SELECT id
FROM res_partner
{where} ({email} {operator} {percent}
OR {display_name} {operator} {percent})
ORDER BY {display_name}
""".format(where=where_str, operator=operator,
email=unaccent('email'),
display_name=unaccent('display_name'),
percent=unaccent('%s'))
where_clause_params += [search_name, search_name]
if limit:

View File

@ -1,4 +1,6 @@
import unittest2
from openerp.osv.expression import get_unaccent_wrapper
from openerp.osv.orm import BaseModel
import openerp.tests.common as common
@ -123,6 +125,7 @@ class test_expression(common.TransactionCase):
def test_20_auto_join(self):
registry, cr, uid = self.registry, self.cr, self.uid
unaccent = get_unaccent_wrapper(cr)
# Get models
partner_obj = registry('res.partner')
@ -179,8 +182,11 @@ class test_expression(common.TransactionCase):
sql_query = self.query_list[0].get_sql()
self.assertIn('res_partner_bank', sql_query[0],
"_auto_join off: ('bank_ids.name', 'like', '..') first query incorrect main table")
self.assertIn('"res_partner_bank"."name" like %s', sql_query[1],
expected = "%s like %s" % (unaccent('"res_partner_bank"."name"'), unaccent('%s'))
self.assertIn(expected, sql_query[1],
"_auto_join off: ('bank_ids.name', 'like', '..') first query incorrect where condition")
self.assertEqual(set(['%' + name_test + '%']), set(sql_query[2]),
"_auto_join off: ('bank_ids.name', 'like', '..') first query incorrect parameter")
sql_query = self.query_list[2].get_sql()
@ -216,8 +222,11 @@ class test_expression(common.TransactionCase):
"_auto_join on: ('bank_ids.name', 'like', '..') query incorrect main table")
self.assertIn('"res_partner_bank" as "res_partner__bank_ids"', sql_query[0],
"_auto_join on: ('bank_ids.name', 'like', '..') query incorrect join")
self.assertIn('"res_partner__bank_ids"."name" like %s', sql_query[1],
expected = "%s like %s" % (unaccent('"res_partner__bank_ids"."name"'), unaccent('%s'))
self.assertIn(expected, sql_query[1],
"_auto_join on: ('bank_ids.name', 'like', '..') query incorrect where condition")
self.assertIn('"res_partner"."id"="res_partner__bank_ids"."partner_id"', sql_query[1],
"_auto_join on: ('bank_ids.name', 'like', '..') query incorrect join condition")
self.assertEqual(set(['%' + name_test + '%']), set(sql_query[2]),
@ -295,8 +304,11 @@ class test_expression(common.TransactionCase):
sql_query = self.query_list[0].get_sql()
self.assertIn('"res_country"', sql_query[0],
"_auto_join on for state_id: ('state_id.country_id.code', 'like', '..') query 1 incorrect main table")
self.assertIn('"res_country"."code" like %s', sql_query[1],
expected = "%s like %s" % (unaccent('"res_country"."code"'), unaccent('%s'))
self.assertIn(expected, sql_query[1],
"_auto_join on for state_id: ('state_id.country_id.code', 'like', '..') query 1 incorrect where condition")
self.assertEqual(['%' + name_test + '%'], sql_query[2],
"_auto_join on for state_id: ('state_id.country_id.code', 'like', '..') query 1 incorrect parameter")
sql_query = self.query_list[1].get_sql()
@ -326,8 +338,11 @@ class test_expression(common.TransactionCase):
"_auto_join on for country_id: ('state_id.country_id.code', 'like', '..') query 1 incorrect main table")
self.assertIn('"res_country" as "res_country_state__country_id"', sql_query[0],
"_auto_join on for country_id: ('state_id.country_id.code', 'like', '..') query 1 incorrect join")
self.assertIn('"res_country_state__country_id"."code" like %s', sql_query[1],
expected = "%s like %s" % (unaccent('"res_country_state__country_id"."code"'), unaccent('%s'))
self.assertIn(expected, sql_query[1],
"_auto_join on for country_id: ('state_id.country_id.code', 'like', '..') query 1 incorrect where condition")
self.assertIn('"res_country_state"."country_id"="res_country_state__country_id"."id"', sql_query[1],
"_auto_join on for country_id: ('state_id.country_id.code', 'like', '..') query 1 incorrect join condition")
self.assertEqual(['%' + name_test + '%'], sql_query[2],
@ -357,8 +372,11 @@ class test_expression(common.TransactionCase):
"_auto_join on: ('state_id.country_id.code', 'like', '..') query incorrect join")
self.assertIn('"res_country" as "res_partner__state_id__country_id"', sql_query[0],
"_auto_join on: ('state_id.country_id.code', 'like', '..') query incorrect join")
self.assertIn('"res_partner__state_id__country_id"."code" like %s', sql_query[1],
expected = "%s like %s" % (unaccent('"res_partner__state_id__country_id"."code"'), unaccent('%s'))
self.assertIn(expected, sql_query[1],
"_auto_join on: ('state_id.country_id.code', 'like', '..') query incorrect where condition")
self.assertIn('"res_partner"."state_id"="res_partner__state_id"."id"', sql_query[1],
"_auto_join on: ('state_id.country_id.code', 'like', '..') query incorrect join condition")
self.assertIn('"res_partner__state_id"."country_id"="res_partner__state_id__country_id"."id"', sql_query[1],
@ -384,7 +402,9 @@ class test_expression(common.TransactionCase):
"_auto_join on one2many with domains incorrect result")
# Test produced queries that domains effectively present
sql_query = self.query_list[0].get_sql()
self.assertIn('"res_partner__child_ids__bank_ids"."acc_number" like %s', sql_query[1],
expected = "%s like %s" % (unaccent('"res_partner__child_ids__bank_ids"."acc_number"'), unaccent('%s'))
self.assertIn(expected, sql_query[1],
"_auto_join on one2many with domains incorrect result")
# TDE TODO: check first domain has a correct table name
self.assertIn('"res_partner__child_ids"."name" = %s', sql_query[1],

View File

@ -429,6 +429,10 @@ def select_distinct_from_where_not_null(cr, select_field, from_table):
cr.execute('SELECT distinct("%s") FROM "%s" where "%s" is not null' % (select_field, from_table, select_field))
return [r[0] for r in cr.fetchall()]
def get_unaccent_wrapper(cr):
if openerp.modules.registry.RegistryManager.get(cr.dbname).has_unaccent:
return lambda x: "unaccent(%s)" % (x,)
return lambda x: x
# --------------------------------------------------
# ExtendedLeaf class for managing leafs and contexts
@ -630,7 +634,7 @@ class expression(object):
:attr list expression: the domain expression, that will be normalized
and prepared
"""
self.has_unaccent = openerp.modules.registry.RegistryManager.get(cr.dbname).has_unaccent
self._unaccent = get_unaccent_wrapper(cr)
self.joins = []
self.root_model = table
@ -1019,7 +1023,6 @@ class expression(object):
push(create_substitution_leaf(leaf, (left, operator, right), working_model))
elif field.translate and right:
field = left
need_wildcard = operator in ('like', 'ilike', 'not like', 'not ilike')
sql_operator = {'=like': 'like', '=ilike': 'ilike'}.get(operator, operator)
if need_wildcard:
@ -1031,16 +1034,13 @@ class expression(object):
sql_operator = sql_operator[4:] if sql_operator[:3] == 'not' else '='
inselect_operator = 'not inselect'
trans_left = 'value'
left = '"%s"' % (left,)
instr = '%s'
unaccent = self._unaccent if sql_operator.endswith('like') else lambda x: x
if self.has_unaccent and sql_operator.endswith('like'):
assert isinstance(right, basestring)
trans_left = 'unaccent(value)'
left = 'unaccent(%s)' % (left,)
instr = 'unaccent(%s)'
elif sql_operator == 'in':
trans_left = unaccent('value')
quote_left = unaccent(_quote(left))
instr = unaccent('%s')
if sql_operator == 'in':
# params will be flatten by to_sql() => expand the placeholders
instr = '(%s)' % ', '.join(['%s'] * len(right))
@ -1056,10 +1056,10 @@ class expression(object):
WHERE {left} {operator} {right}
)
""".format(trans_left=trans_left, operator=sql_operator,
right=instr, table=working_model._table, left=left)
right=instr, table=working_model._table, left=quote_left)
params = (
working_model._name + ',' + field,
working_model._name + ',' + left,
context.get('lang') or 'en_US',
'model',
right,
@ -1185,10 +1185,9 @@ class expression(object):
if left in model._columns:
format = need_wildcard and '%s' or model._columns[left]._symbol_set[0]
if self.has_unaccent and sql_operator.endswith('like'):
query = '(unaccent(%s."%s") %s unaccent(%s))' % (table_alias, left, sql_operator, format)
else:
query = '(%s."%s" %s %s)' % (table_alias, left, sql_operator, format)
unaccent = self._unaccent if sql_operator.endswith('like') else lambda x: x
column = '%s.%s' % (table_alias, _quote(left))
query = '(%s %s %s)' % (unaccent(column), sql_operator, unaccent(format))
elif left in MAGIC_COLUMNS:
query = "(%s.\"%s\" %s %%s)" % (table_alias, left, sql_operator)
params = right