[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:
@@ -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
|
||||
|
||||
@@ -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]
|
||||
|
||||
Reference in New Issue
Block a user