[IMP] expression: some tests, some cleaning, and a fix:

child_of_right_to_ids() had an uninitialized field_obj variable.

bzr revid: vmt@openerp.com-20110725150721-mm4fhnhm17ill29b
This commit is contained in:
Vo Minh Thu 2011-07-25 17:07:21 +02:00
parent a9e89a49b2
commit 5858a06d5d
2 changed files with 77 additions and 21 deletions

View File

@ -178,7 +178,7 @@
res_ids.sort()
assert res_ids == all_ids, "Searching against empty set failed, returns %r" % res_ids
-
Equivalent queries.
Equivalent queries, integer and string.
-
!python {model: res.partner }: |
all_ids = self.search(cr, uid, [])
@ -194,6 +194,8 @@
# res_5 = self.search(cr, uid, [('id', 'in', one)]) # TODO make it permitted, just like for child_of
res_6 = self.search(cr, uid, [('id', 'in', [one])])
res_7 = self.search(cr, uid, [('name', '=', record.name)])
res_8 = self.search(cr, uid, [('name', 'in', [record.name])])
# res_9 = self.search(cr, uid, [('name', 'in', record.name)]) # TODO
assert [one] == res_1
assert [one] == res_2
assert [one] == res_3
@ -201,6 +203,51 @@
#assert [one] == res_5
assert [one] == res_6
assert [one] == res_7
-
Need a company with a parent_id.
-
!record {model: res.company, id: ymltest_company3}:
name: Acme 3
-
Need a company with a parent_id.
-
!record {model: res.company, id: ymltest_company4}:
name: Acme 4
parent_id: ymltest_company3
-
Equivalent queries, one2many.
-
!python {model: res.company }: |
# Search the company via its one2many (the one2many must point back at the company).
company = self.browse(cr, uid, ref('ymltest_company3'))
default_company = self.browse(cr, uid, 1)
# one2many towards same model
res_1 = self.search(cr, uid, [('child_ids', 'in', [x.id for x in company.child_ids])])
res_2 = self.search(cr, uid, [('child_ids', 'in', [company.child_ids[0].id])])
# one2many towards another model
res_3 = self.search(cr, uid, [('currency_ids', 'in', [x.id for x in default_company.currency_ids])])
res_4 = self.search(cr, uid, [('currency_ids', 'in', [default_company.currency_ids[0].id])])
assert res_1 == [ref('ymltest_company3')]
assert res_2 == [ref('ymltest_company3')]
assert res_3 == [1]
assert res_4 == [1]
# child_of x returns x and its children (direct or not).
company = self.browse(cr, uid, ref('ymltest_company3'))
expected = [ref('ymltest_company3'), ref('ymltest_company4')]
expected.sort()
res_1 = self.search(cr, uid, [('id', 'child_of', [ref('ymltest_company3')])])
res_1.sort()
res_2 = self.search(cr, uid, [('id', 'child_of', ref('ymltest_company3'))])
res_2.sort()
#res_3 = self.search(cr, uid, [('id', 'child_of', [company.name])])
#res_3.sort()
res_4 = self.search(cr, uid, [('id', 'child_of', company.name)])
res_4.sort()
assert res_1 == expected
assert res_2 == expected
#assert res_3 == expected
assert res_4 == expected
-
Verify that normalize_domain() works.
-

View File

@ -147,6 +147,7 @@ class expression(object):
# assign self.__exp with the normalized, parsed domain.
self.parse(cr, uid, normalize(exp), table, context)
# TODO used only for osv_memory
@property
def exp(self):
return self.__exp[:]
@ -155,8 +156,8 @@ class expression(object):
""" transform the leafs of the expression """
self.__exp = exp
def _rec_get(right, table, parent=None, left='id', prefix=''):
ids = child_of_right_to_ids(right, 'ilike')
def child_of_domain(left, right, table, parent=None, prefix=''):
ids = right
if table._parent_store and (not table.pool._init):
# TODO: Improve where joins are implemented for many with '.', replace by:
# doms += ['&',(prefix+'.parent_left','<',o.parent_right),(prefix+'.parent_left','>=',o.parent_left)]
@ -177,7 +178,7 @@ class expression(object):
return [(left, 'in', rg(ids, table, parent or table._parent_name))]
# TODO rename this function as it is not strictly for 'child_of', but also for 'in'...
def child_of_right_to_ids(value, operator):
def child_of_right_to_ids(value, operator, field_obj):
""" Normalize a single id, or a string, or a list of ids to a list of ids.
"""
if isinstance(value, basestring):
@ -198,25 +199,30 @@ class expression(object):
continue
left, operator, right = e
operator = operator.lower()
working_table = table
main_table = table
working_table = table # The table containing the field (the name provided in the left operand)
fargs = left.split('.', 1)
# If the field is _inherits'd, search for the working_table,
# and extract the field.
if fargs[0] in table._inherit_fields:
while True:
field = main_table._columns.get(fargs[0])
field = working_table._columns.get(fargs[0])
if field:
self.__field_tables[i] = working_table
break
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.add(working_table)
main_table = working_table
next_table = working_table.pool.get(working_table._inherit_fields[fargs[0]][0])
if next_table not in self.__all_tables:
self.__joins.append('%s.%s=%s.%s' % (next_table._table, 'id', working_table._table, working_table._inherits[next_table._name]))
self.__all_tables.add(next_table)
working_table = next_table
# Or (try to) directly extract the field.
else:
field = working_table._columns.get(fargs[0])
field = working_table._columns.get(fargs[0])
if not field:
if left == 'id' and operator == 'child_of':
dom = _rec_get(right, working_table)
ids2 = child_of_right_to_ids(right, 'ilike', table)
dom = child_of_domain(left, ids2, working_table)
self.__exp = self.__exp[:i] + dom + self.__exp[i+1:]
continue
@ -263,9 +269,11 @@ class expression(object):
# Applying recursivity on field(one2many)
if operator == 'child_of':
if field._obj != working_table._name:
dom = _rec_get(right, field_obj, left=left, prefix=field._obj)
ids2 = child_of_right_to_ids(right, 'ilike', field_obj)
dom = child_of_domain(left, ids2, field_obj, prefix=field._obj)
else:
dom = _rec_get(right, working_table, parent=left)
ids2 = child_of_right_to_ids(right, 'ilike', field_obj)
dom = child_of_domain('id', ids2, working_table, parent=left)
self.__exp = self.__exp[:i] + dom + self.__exp[i+1:]
else:
@ -287,7 +295,6 @@ class expression(object):
call_null = False
self.__exp[i] = FALSE_LEAF
else:
call_null = True
operator = 'in' # operator changed because ids are directly related to main object
else:
call_null = False
@ -310,7 +317,8 @@ class expression(object):
return ids
return execute_recursive_in(cr, field._id1, field._rel, field._id2, ids, operator)
dom = _rec_get(right, field_obj)
ids2 = child_of_right_to_ids(right, 'ilike', field_obj)
dom = child_of_domain('id', ids2, field_obj)
ids2 = field_obj.search(cr, uid, dom, context=context)
self.__exp[i] = ('id', 'in', _rec_convert(ids2))
else:
@ -331,7 +339,6 @@ class expression(object):
call_null_m2m = False
self.__exp[i] = FALSE_LEAF
else:
call_null_m2m = True
operator = 'in' # operator changed because ids are directly related to main object
else:
call_null_m2m = False
@ -349,9 +356,11 @@ class expression(object):
elif field._type == 'many2one':
if operator == 'child_of':
if field._obj != working_table._name:
dom = _rec_get(right, field_obj, left=left, prefix=field._obj)
ids2 = child_of_right_to_ids(right, 'ilike', field_obj)
dom = child_of_domain(left, ids2, field_obj, prefix=field._obj)
else:
dom = _rec_get(right, working_table, parent=left)
ids2 = child_of_right_to_ids(right, 'ilike', field_obj)
dom = child_of_domain('id', ids2, working_table, parent=left)
self.__exp = self.__exp[:i] + dom + self.__exp[i+1:]
else:
def _get_expression(field_obj,cr, uid, left, right, operator, context=None):