[MERGE] OPW 578099: ir.filters should be translated according to the user language
[odoo/odoo.git] / bin / osv / expression.py
index 16f34c7..f83c044 100644 (file)
@@ -57,7 +57,7 @@ class expression(object):
                     subids = ids[i:i+cr.IN_MAX]
                     cr.execute('SELECT "%s"'    \
                                '  FROM "%s"'    \
-                               '  WHERE "%s" in %%s' % (s, f, w),(tuple(subids),))
+                               '  WHERE "%s" IN %%s' % (s, f, w),(tuple(subids),))
                     res.extend([r[0] for r in cr.fetchall()])
         else:
             cr.execute('SELECT distinct("%s")'    \
@@ -76,6 +76,9 @@ class expression(object):
         self.__main_table = None # 'root' table. set by parse()
         self.__DUMMY_LEAF = (1, '=', 1) # a dummy leaf that must not be parsed or sql generated
 
+    @property
+    def exp(self):
+        return self.__exp[:]
 
     def parse(self, cr, uid, table, context):
         """ transform the leafs of the expression """
@@ -112,6 +115,7 @@ class expression(object):
             if self._is_operator(e) or e == self.__DUMMY_LEAF:
                 continue
             left, operator, right = e
+            operator = operator.lower()
             working_table = table
             main_table = table
             fargs = left.split('.', 1)
@@ -139,28 +143,39 @@ class expression(object):
             if len(fargs) > 1:
                 if field._type == 'many2one':
                     right = field_obj.search(cr, uid, [(fargs[1], operator, right)], context=context)
-                    self.__exp[i] = (fargs[0], 'in', right)
+                    if right == []:
+                        self.__exp[i] = ( 'id', '=', 0 )
+                    else:
+                        self.__exp[i] = (fargs[0], 'in', right)
                 # Making search easier when there is a left operand as field.o2m or field.m2m
                 if field._type in ['many2many','one2many']:
                     right = field_obj.search(cr, uid, [(fargs[1], operator, right)], context=context)
                     right1 = table.search(cr, uid, [(fargs[0],'in', right)], context=context)
-                    self.__exp[i] = ('id', 'in', right1)
-                continue
+                    if right1 == []:
+                        self.__exp[i] = ( 'id', '=', 0 )
+                    else:
+                        self.__exp[i] = ('id', 'in', right1)
+
+                if not isinstance(field,fields.property):
+                    continue
 
-            if field._properties and ((not field.store) or field._fnct_search):
-                # this is a function field
+            if field._properties and not field.store:
+                # this is a function field that is not stored
                 if not field._fnct_search:
                     # the function field doesn't provide a search function and doesn't store
                     # values in the database, so we must ignore it : we generate a dummy leaf
                     self.__exp[i] = self.__DUMMY_LEAF
                 else:
                     subexp = field.search(cr, uid, table, left, [self.__exp[i]], context=context)
-                    # we assume that the expression is valid
-                    # we create a dummy leaf for forcing the parsing of the resulting expression
-                    self.__exp[i] = '&'
-                    self.__exp.insert(i + 1, self.__DUMMY_LEAF)
-                    for j, se in enumerate(subexp):
-                        self.__exp.insert(i + 2 + j, se)
+                    if not subexp:
+                        self.__exp[i] = self.__DUMMY_LEAF
+                    else:
+                        # we assume that the expression is valid
+                        # we create a dummy leaf for forcing the parsing of the resulting expression
+                        self.__exp[i] = '&'
+                        self.__exp.insert(i + 1, self.__DUMMY_LEAF)
+                        for j, se in enumerate(subexp):
+                            self.__exp.insert(i + 2 + j, se)
             # else, the value of the field is store in the database, so we search on it
 
             elif field._type == 'one2many':
@@ -179,7 +194,7 @@ class expression(object):
                 else:
                     call_null = True
 
-                    if right:
+                    if right is not False:
                         if isinstance(right, basestring):
                             ids2 = [x[0] for x in field_obj.name_search(cr, uid, right, [], operator, context=context, limit=None)]
                             if ids2:
@@ -228,11 +243,11 @@ class expression(object):
                     self.__exp[i] = ('id', 'in', _rec_convert(ids2))
                 else:
                     call_null_m2m = True
-                    if right:
+                    if right is not False:
                         if isinstance(right, basestring):
                             res_ids = [x[0] for x in field_obj.name_search(cr, uid, right, [], operator, context=context)]
                             if res_ids:
-                                opeartor = 'in'
+                                operator = 'in'
                         else:
                             if not isinstance(right, list):
                                 res_ids = [right]
@@ -275,15 +290,54 @@ class expression(object):
                         dom = _rec_get(ids2, working_table, parent=left)
                     self.__exp = self.__exp[:i] + dom + self.__exp[i+1:]
                 else:
-                    if isinstance(right, basestring): # and not isinstance(field, fields.related):
+                    def _get_expression(field_obj,cr, uid, left, right, operator, context=None):
+                        if context is None:
+                            context = {}                        
                         c = context.copy()
                         c['active_test'] = False
+                        #Special treatment to ill-formed domains
+                        operator = ( operator in ['<','>','<=','>='] ) and 'in' or operator
+                        
+                        dict_op = {'not in':'!=','in':'=','=':'in','!=':'not in','<>':'not in'}
+                        if isinstance(right,tuple):
+                            right = list(right)
+                        if (not isinstance(right,list)) and operator in ['not in','in']:
+                            operator = dict_op[operator]
+                        elif isinstance(right,list) and operator in ['<>','!=','=']: #for domain (FIELD,'=',['value1','value2'])
+                            operator = dict_op[operator]
                         res_ids = field_obj.name_search(cr, uid, right, [], operator, limit=None, context=c)
                         if not res_ids:
-                            self.__exp[i] = ('id','=',0)
+                           return ('id','=',0)
                         else:
                             right = map(lambda x: x[0], res_ids)
-                            self.__exp[i] = (left, 'in', right)
+                            return (left, 'in', right)
+
+                    m2o_str = False
+                    if right:
+                        if isinstance(right, basestring): # and not isinstance(field, fields.related):
+                            m2o_str = True
+                        elif isinstance(right,(list,tuple)):
+                            m2o_str = True
+                            for ele in right:
+                                if not isinstance(ele, basestring): 
+                                    m2o_str = False
+                                    break
+                    elif right == []:
+                        m2o_str = False
+                        if operator in ('not in', '!=', '<>'):
+                            # (many2one not in []) should return all records
+                            self.__exp[i] = self.__DUMMY_LEAF
+                        else:
+                            self.__exp[i] = ('id','=',0)
+                    else:
+                        new_op = '='
+                        if operator in  ['not like','not ilike','not in','<>','!=']:
+                            new_op = '!='
+                        #Is it ok to put 'left' and not 'id' ?
+                        self.__exp[i] = (left,new_op,False)
+                        
+                    if m2o_str:
+                        self.__exp[i] = _get_expression(field_obj,cr, uid, left, right, operator, context=context)
             else:
                 # other field type
                 # add the time part to datetime field when it's not there: