[FIX] core: change behavior of x2m inegative domains using name_search.

Domains like `[('x2m_field_ids', 'not ilike', 'foo')]` now have a more
logical semantic. The negation is applied on the relation and not the
`name_search`.
This commit is contained in:
Christophe Simonis
2015-07-23 15:17:40 +02:00
parent 0d1fbabc28
commit 6a962b9594
2 changed files with 41 additions and 5 deletions
@@ -94,6 +94,41 @@ class test_expression(common.TransactionCase):
# self.assertTrue(a not in with_any_other_than_a, "Search for category_id with any other than cat_a failed (1).")
# self.assertTrue(ab in with_any_other_than_a, "Search for category_id with any other than cat_a failed (2).")
def test_05_not_str_m2m(self):
registry, cr, uid = self.registry, self.cr, self.uid
partners = registry('res.partner')
categories = registry('res.partner.category')
cats = {}
for cat in 'A B AB'.split():
cats[cat] = categories.create(cr, uid, {'name': cat})
_partners = {
'0': [],
'a': [cats['A']],
'b': [cats['B']],
'ab': [cats['AB']],
'a b': [cats['A'], cats['B']],
'b ab': [cats['B'], cats['AB']],
}
pids = {}
for p in _partners:
pids[p] = partners.create(cr, uid, {'name': p, 'category_id': [(6, 0, _partners[p])]})
base_domain = [('id', 'in', pids.values())]
def test(op, value, expected):
ids = set(partners.search(cr, uid, base_domain + [('category_id', op, value)]))
expected_ids = set(map(pids.__getitem__, expected))
self.assertSetEqual(ids, expected_ids, '%s %r should return %r' % (op, value, expected))
test('=', 'A', ['a', 'a b'])
test('!=', 'B', ['0', 'a', 'ab'])
test('like', 'A', ['a', 'ab', 'a b', 'b ab'])
test('not ilike', 'B', ['0', 'a'])
test('not like', 'AB', ['0', 'a', 'b', 'a b'])
def test_10_expression_parse(self):
# TDE note: those tests have been added when refactoring the expression.parse() method.
# They come in addition to the already existing test_osv_expression.yml; maybe some tests
+6 -5
View File
@@ -927,9 +927,10 @@ class expression(object):
if right is not False:
if isinstance(right, basestring):
ids2 = [x[0] for x in comodel.name_search(cr, uid, right, [], operator, context=context, limit=None)]
op = {'!=': '=', 'not like': 'like', 'not ilike': 'ilike'}.get(operator, operator)
ids2 = [x[0] for x in comodel.name_search(cr, uid, right, [], op, context=context, limit=None)]
if ids2:
operator = 'in'
operator = 'not in' if operator in NEGATIVE_TERM_OPERATORS else 'in'
elif isinstance(right, collections.Iterable):
ids2 = right
else:
@@ -953,7 +954,6 @@ class expression(object):
elif column._type == 'many2many':
rel_table, rel_id1, rel_id2 = column._sql_names(model)
#FIXME
if operator == 'child_of':
def _rec_convert(ids):
if comodel == model:
@@ -968,9 +968,10 @@ class expression(object):
call_null_m2m = True
if right is not False:
if isinstance(right, basestring):
res_ids = [x[0] for x in comodel.name_search(cr, uid, right, [], operator, context=context)]
op = {'!=': '=', 'not like': 'like', 'not ilike': 'ilike'}.get(operator, operator)
res_ids = [x[0] for x in comodel.name_search(cr, uid, right, [], op, context=context)]
if res_ids:
operator = 'in'
operator = 'not in' if operator in NEGATIVE_TERM_OPERATORS else 'in'
else:
if not isinstance(right, list):
res_ids = [right]