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
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):
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)
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':
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:
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:
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)
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: