[FIX] expression: allow exclusion of records with translated fields
authorChristophe Simonis <chs@openerp.com>
Mon, 6 Jan 2014 19:51:43 +0000 (20:51 +0100)
committerChristophe Simonis <chs@openerp.com>
Mon, 6 Jan 2014 19:51:43 +0000 (20:51 +0100)
lp bug: https://launchpad.net/bugs/1071710 fixed

bzr revid: chs@openerp.com-20140106195143-u3gxmfm9ifg9k3u0

bin/addons/base/test/test_osv_expression.yml
bin/osv/expression.py

index 4916fe0..e8b199f 100644 (file)
         res_ids = self.search(cr, uid, [('company_id.partner_id', 'not in', [])])
         res_ids.sort()
         assert res_ids == all_ids, "Searching against empty set failed, returns %r" % res_ids
+-
+    Check that we can exclude translated fields (bug lp:1071710)
+-
+    !python {model: res.country}: |
+        # first install french language
+        BLI = self.pool.get('base.language.install')
+        BLI.lang_install(cr, uid, [BLI.create(cr, uid, {'lang': 'fr_FR'})])
+
+        be_id = self.search(cr, uid, [('name', '=', 'Belgium')])[0]
+
+        ctx = {'lang': 'fr_FR'}
+        not_be = self.search(cr, uid, [('name', '!=', 'Belgique')], context=ctx)
 
+        assert be_id not in not_be, "Search match failed"
index f83c044..6d72566 100644 (file)
@@ -37,7 +37,7 @@ class expression(object):
 
     def _is_leaf(self, element, internal=False):
         OPS = ('=', '!=', '<>', '<=', '<', '>', '>=', '=?', '=like', '=ilike', 'like', 'not like', 'ilike', 'not ilike', 'in', 'not in', 'child_of')
-        INTERNAL_OPS = OPS + ('inselect',)
+        INTERNAL_OPS = OPS + ('inselect', 'not inselect')
         return (isinstance(element, tuple) or isinstance(element, list)) \
            and len(element) == 3 \
            and (((not internal) and element[1] in OPS) \
@@ -358,6 +358,11 @@ class expression(object):
 
                     operator = operator == '=like' and 'like' or operator
 
+                    new_op = 'inselect'
+                    if operator in ['not like', 'not ilike', 'not in', '<>', '!=']:
+                        new_op = 'not inselect'
+                        operator = {'not like': 'like', 'not ilike': 'ilike', 'not in': 'in', '<>': '=', '!=': '='}[operator]
+
                     query1 = '( SELECT res_id'          \
                              '    FROM ir_translation'  \
                              '   WHERE name = %s'       \
@@ -365,7 +370,7 @@ class expression(object):
                              '     AND type = %s'
                     instr = ' %s'
                     #Covering in,not in operators with operands (%s,%s) ,etc.
-                    if operator in ['in','not in']:
+                    if operator == 'in':
                         instr = ','.join(['%s'] * len(right))
                         query1 += '     AND value ' + operator +  ' ' +" (" + instr + ")"   \
                              ') UNION ('                \
@@ -386,7 +391,7 @@ class expression(object):
                               right,
                              ]
 
-                    self.__exp[i] = ('id', 'inselect', (query1, query2))
+                    self.__exp[i] = ('id', new_op, (query1, query2))
 
         return self
 
@@ -398,6 +403,9 @@ class expression(object):
         if operator == 'inselect':
             query = '(%s.%s in (%s))' % (table._table, left, right[0])
             params = right[1]
+        elif operator == 'not inselect':
+            query = '(%s.%s not in (%s))' % (table._table, left, right[0])
+            params = right[1]
         elif operator in ['in', 'not in']:
             params = right and right[:] or []
             len_before = len(params)