Add Modified Preorder Tree Traversal
Remove _parent_name Fix child_of on non tree field
This commit is contained in:
1 parent
bcbabbc61f
commit
6e5b06cb45
3 files changed
+134
-28
No files matched your search
@@ -309,9 +309,11 @@ class Many2One(Column):
|
||||
_symbol_f = lambda x: x and int(x) or None
|
||||
_symbol_set = (_symbol_c, _symbol_f)
|
||||
|
||||
def __init__(self, obj, string='unknown', **args):
|
||||
def __init__(self, obj, string='unknown', left=None, right=None, **args):
|
||||
Column.__init__(self, string=string, **args)
|
||||
self._obj = obj
|
||||
self.left = left
|
||||
self.right = right
|
||||
|
||||
# TODO: speed improvement
|
||||
# name is the name of the relation field
|
||||
|
||||
+131
-26
@@ -195,7 +195,6 @@ class ORM(object):
|
||||
_name = None
|
||||
_rec_name = 'name'
|
||||
_order_name = None # Use to force order field when sorting on Many2One
|
||||
_parent_name = 'parent'
|
||||
_date_name = 'date'
|
||||
_order = None
|
||||
_inherits = {} #XXX remove from class instance
|
||||
@@ -725,6 +724,17 @@ class ORM(object):
|
||||
if line2:
|
||||
cursor.execute(line2)
|
||||
|
||||
for k in self._columns:
|
||||
field = self._columns[k]
|
||||
if isinstance(field, fields.Many2One) \
|
||||
and field._obj == self._name \
|
||||
and field.left and field.right:
|
||||
cursor.execute('SELECT id FROM "%s" ' \
|
||||
'WHERE "%s" IS NULL OR "%s" IS NULL' % \
|
||||
(self._table, field.left, field.right))
|
||||
if cursor.rowcount:
|
||||
self._rebuild_tree(cursor, 0, k, False, 0)
|
||||
|
||||
def __init__(self):
|
||||
self._rpc_allowed = [
|
||||
'read',
|
||||
@@ -1567,6 +1577,20 @@ class ORM(object):
|
||||
|
||||
self._validate(cursor, user, ids)
|
||||
|
||||
# Check for Modified Preorder Tree Traversal
|
||||
for k in self._columns:
|
||||
field = self._columns[k]
|
||||
if isinstance(field, fields.Many2One) \
|
||||
and field._obj == self._name \
|
||||
and field.left and field.right:
|
||||
if field.left in vals or field.right in vals:
|
||||
raise ExceptORM('Error', 'You can not update fields: ' \
|
||||
'"%s", "%s"' % (field.left, field.right))
|
||||
if k in vals:
|
||||
for object_id in ids:
|
||||
self._update_tree(cursor, user, object_id, k,
|
||||
field.left, field.right)
|
||||
|
||||
# Restart rule cache
|
||||
if self.pool.get('ir.rule.group').search(cursor, 0, [
|
||||
('model.model', '=', self._name),
|
||||
@@ -1709,6 +1733,14 @@ class ORM(object):
|
||||
|
||||
self._validate(cursor, user, [id_new])
|
||||
|
||||
# Check for Modified Preorder Tree Traversal
|
||||
for k in self._columns:
|
||||
field = self._columns[k]
|
||||
if isinstance(field, fields.Many2One) \
|
||||
and field._obj == self._name \
|
||||
and field.left and field.right:
|
||||
self._update_tree(cursor, user, id_new, k, field.left, field.right)
|
||||
|
||||
wf_service = LocalService("workflow")
|
||||
wf_service.trg_create(user, self._name, id_new, cursor)
|
||||
return id_new
|
||||
@@ -2252,24 +2284,26 @@ class ORM(object):
|
||||
context=context)
|
||||
return ids + _rec_get(ids2, table, parent)
|
||||
|
||||
def _rec_convert(ids):
|
||||
if self.pool.get(field._obj)==self:
|
||||
return ids
|
||||
if not len(ids):
|
||||
return []
|
||||
cursor.execute(
|
||||
'SELECT "' + field._id1 + '" ' \
|
||||
'FROM "' + field._rel + '" ' \
|
||||
'WHERE "' + field._id2 + '" IN (' + \
|
||||
','.join(['%s' for x in ids]) + ')',
|
||||
[str(x) for x in ids])
|
||||
if field._obj != table._name:
|
||||
raise ExceptORM('Error', 'Programming error: ' \
|
||||
'child_of on field "%s" is not allowed!' % \
|
||||
(args[i][0],))
|
||||
|
||||
ids = [x[0] for x in cursor.fetchall()]
|
||||
return ids
|
||||
|
||||
args[i] = ('id', 'in', _rec_convert(ids2 + _rec_get(ids2,
|
||||
self.pool.get(field._obj),
|
||||
self.pool.get(field._obj)._parent_name)))
|
||||
parent = None
|
||||
for k in table._columns:
|
||||
field2 = table._columns[k]
|
||||
if field2._type == 'many2many' \
|
||||
and field._rel == field2._rel \
|
||||
and field._id1 == field2._id2 \
|
||||
and field._id2 == field2._id1:
|
||||
parent = k
|
||||
break
|
||||
if not parent:
|
||||
raise ExceptORM('Error', 'Programming error: ' \
|
||||
'child_of on field "%s" is not allowed!' % \
|
||||
(args[i][0],))
|
||||
args[i] = ('id', 'in', ids2 + _rec_get(ids2,
|
||||
table, parent))
|
||||
else:
|
||||
if isinstance(args[i][2], basestring):
|
||||
res_ids = [x[0] for x in self.pool.get(field._obj
|
||||
@@ -2317,12 +2351,32 @@ class ORM(object):
|
||||
return ids + _rec_get(ids2, table, parent)
|
||||
|
||||
if field._obj != table._name:
|
||||
args[i] = (args[i][0], 'in', ids2 + _rec_get(ids2,
|
||||
self.pool.get(field._obj), table._parent_name),
|
||||
table)
|
||||
raise ExceptORM('Error', 'Programming error: ' \
|
||||
'child_of on field "%s" is not allowed!' % \
|
||||
(args[i][0],))
|
||||
else:
|
||||
args[i] = ('id', 'in', ids2 + _rec_get(ids2, table,
|
||||
args[i][0]), table)
|
||||
if field.left and field.right:
|
||||
cursor.execute('SELECT "' + field.left + '", ' \
|
||||
'"' + field.right + '" ' + \
|
||||
'FROM "' + self._table + '" ' + \
|
||||
'WHERE id IN ' + \
|
||||
'(' + ','.join(['%s' for x in ids2]) + ')',
|
||||
ids2)
|
||||
clause = ''
|
||||
for left, right in cursor.fetchall():
|
||||
if clause:
|
||||
clause += 'OR '
|
||||
clause += '( "' + field.left + '" >= ' + \
|
||||
str(left) + ' ' + \
|
||||
'AND "' + field.right + '" <= ' + \
|
||||
str(right) + ')'
|
||||
|
||||
query = 'SELECT id FROM "' + self._table + '" ' + \
|
||||
'WHERE ' + clause
|
||||
args[i] = ('id', 'inselect', (query, []))
|
||||
else:
|
||||
args[i] = ('id', 'in', ids2 + _rec_get(ids2, table,
|
||||
args[i][0]), table)
|
||||
else:
|
||||
if isinstance(args[i][2], basestring):
|
||||
res_ids = self.pool.get(field._obj).name_search(cursor,
|
||||
@@ -2729,13 +2783,11 @@ class ORM(object):
|
||||
return self.read(cursor, user, ids, fields_names=fields_names,
|
||||
context=context, load=load)
|
||||
|
||||
def check_recursion(self, cursor, user, ids, parent=None):
|
||||
def check_recursion(self, cursor, user, ids, parent='parent'):
|
||||
'''
|
||||
Function that check if there is no recursion in the tree
|
||||
composed with parent as parent field name.
|
||||
'''
|
||||
if parent is None:
|
||||
parent = self._parent_name
|
||||
ids_parent = ids[:]
|
||||
while len(ids_parent):
|
||||
ids_parent2 = []
|
||||
@@ -2765,4 +2817,57 @@ class ORM(object):
|
||||
return res[0]
|
||||
return 0
|
||||
|
||||
def _rebuild_tree(self, cursor, user, parent, parent_id, left):
|
||||
'''
|
||||
Rebuild left, right value for the tree.
|
||||
'''
|
||||
right = left + 1
|
||||
|
||||
child_ids = self.search(cursor, 0, [
|
||||
(parent, '=', parent_id),
|
||||
])
|
||||
|
||||
for child in self.browse(cursor, 0, child_ids):
|
||||
right = self._rebuild_tree(cursor, user, parent, child.id, right)
|
||||
|
||||
self.write(cursor, 0, parent_id, {
|
||||
'left': left,
|
||||
'right': right,
|
||||
})
|
||||
return right + 1
|
||||
|
||||
def _update_tree(self, cursor, user, object_id, field_name, left, right):
|
||||
'''
|
||||
Update left, right values for the tree.
|
||||
'''
|
||||
cursor.execute('SELECT "' + right + '" ' \
|
||||
'FROM "' + self._table + '" ' \
|
||||
'WHERE id IN (' \
|
||||
'SELECT "' + field_name + '" FROM "' + self._table + '" ' \
|
||||
'WHERE id = %s)', (object_id,))
|
||||
if cursor.rowcount:
|
||||
parent_right = cursor.fetchone()[0]
|
||||
cursor.execute('UPDATE "' + self._table + '" ' \
|
||||
'SET "' + left + '" = "' + left + '" + 2 ' \
|
||||
'WHERE "' + left + '" >= %s', (parent_right,))
|
||||
cursor.execute('UPDATE "' + self._table + '" ' \
|
||||
'SET "' + right + '" = "' + right + '" + 2 ' \
|
||||
'WHERE "' + right + '" >= %s', (parent_right,))
|
||||
cursor.execute('UPDATE "' + self._table + '" ' \
|
||||
'SET "' + left + '" = %s, ' \
|
||||
'"' + right + '" = %s ' \
|
||||
'WHERE id = %s', (parent_right, parent_right + 1, object_id))
|
||||
else:
|
||||
max_right = 0
|
||||
cursor.execute('SELECT MAX("' + right + '") ' \
|
||||
'FROM "' + self._table + '" ' \
|
||||
'WHERE "' + field_name + '" IS NULL')
|
||||
if cursor.rowcount:
|
||||
max_right = cursor.fetchone()[0]
|
||||
|
||||
cursor.execute('UPDATE "' + self._table + '" ' \
|
||||
'SET "' + left + '" = %s, ' \
|
||||
'"' + right + '" = %s ' \
|
||||
'WHERE id = %s', (max_right + 1, max_right + 2, object_id))
|
||||
|
||||
orm = ORM
|
||||
@@ -20,7 +20,6 @@ class Collection(OSV):
|
||||
childs = fields.One2Many('webdav.collection', 'parent', 'Childs')
|
||||
model = fields.Many2One('ir.model', 'Model')
|
||||
domain = fields.Char('Domain', size=250)
|
||||
_parent_name = 'parent'
|
||||
|
||||
def __init__(self):
|
||||
super(Collection, self).__init__()
|
||||
|
||||
Reference in new issue
Block a user