[MERGE] OPW 578099: ir.filters should be translated according to the user language
[odoo/odoo.git] / bin / osv / expression.py
index 3aa77f6..f83c044 100644 (file)
@@ -71,7 +71,7 @@ class expression(object):
             raise ValueError('Bad domain expression: %r' % (exp,))
         self.__exp = exp
         self.__field_tables = {}  # used to store the table to use for the sql generation. key = index of the leaf
-        self.__all_tables = []
+        self.__all_tables = set()
         self.__joins = []
         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
@@ -106,7 +106,7 @@ class expression(object):
                 return [(left, 'in', rg(ids, table, parent or table._parent_name))]
 
         self.__main_table = table
-        self.__all_tables.append(table)
+        self.__all_tables.add(table)
 
         i = -1
         while i + 1<len(self.__exp):
@@ -129,7 +129,7 @@ class expression(object):
                     working_table = main_table.pool.get(main_table._inherit_fields[fargs[0]][0])
                     if working_table not in self.__all_tables:
                         self.__joins.append('%s.%s=%s.%s' % (working_table._table, 'id', main_table._table, main_table._inherits[working_table._name]))
-                        self.__all_tables.append(working_table)
+                        self.__all_tables.add(working_table)
                     main_table = working_table
 
             field = working_table._columns.get(fargs[0], False)
@@ -143,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 field._properties and ((not field.store) or field._fnct_search):
-                # this is a function field
+                if not isinstance(field,fields.property):
+                    continue
+
+            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':
@@ -183,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:
@@ -232,7 +243,7 @@ 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:
@@ -284,11 +295,16 @@ class expression(object):
                             context = {}                        
                         c = context.copy()
                         c['active_test'] = False
-                        dict_op = {'not in':'!=','in':'='}
+                        #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:
                            return ('id','=',0)
@@ -297,14 +313,29 @@ class expression(object):
                             return (left, 'in', right)
 
                     m2o_str = False
-                    if isinstance(right, basestring): # and not isinstance(field, fields.related):
-                        m2o_str = True
-                    elif isinstance(right, list) or isinstance(right, tuple):
-                        m2o_str = True
-                        for ele in right:
-                            if not isinstance(ele, basestring): 
-                                m2o_str = False
-                                break
+                    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: