[IMP] orm: allow import and record creation to defer the computation of parent_left/right,[IMP] orm: do not update parent_left/right if the parent haven't been changed

bzr revid: jvo@tinyerp.com-20100514091143-sl731yzxbw12c058
This commit is contained in:
Christophe Simonis 2010-05-14 14:41:43 +05:30 committed by Jay (Open ERP)
parent 60bec7e475
commit e54441409e
1 changed files with 62 additions and 30 deletions

View File

@ -49,6 +49,7 @@ import string
import sys
import time
import traceback
import datetime
import types
import fields
@ -58,6 +59,7 @@ from tools.translate import _
import copy
import sys
import operator
try:
from lxml import etree
@ -86,7 +88,6 @@ def last_day_of_current_month():
def intersect(la, lb):
return filter(lambda x: x in lb, la)
class except_orm(Exception):
def __init__(self, name, value):
self.name = name
@ -997,6 +998,8 @@ class orm_template(object):
data = pickle.load(file(config.get('import_partial')))
data[filename] = initial_size - len(datas) + original_value
pickle.dump(data, file(config.get('import_partial'),'wb'))
if context.get('defer_parent_store_computation'):
self._parent_store_compute(cr)
cr.commit()
#except Exception, e:
@ -1010,6 +1013,8 @@ class orm_template(object):
#
# TODO: Send a request with the result and multi-thread !
#
if context.get('defer_parent_store_computation'):
self._parent_store_compute(cr)
return (done, 0, 0, 0)
def read(self, cr, user, ids, fields=None, context=None, load='_classic_read'):
@ -2119,6 +2124,8 @@ class orm(orm_template):
return (tables, where_clause)
def _parent_store_compute(self, cr):
if not self._parent_store:
return
logger = netsvc.Logger()
logger.notifyChannel('orm', netsvc.LOG_INFO, 'Computing parent left and right for table %s...' % (self._table, ))
def browse_rec(root, pos=0):
@ -2207,7 +2214,7 @@ class orm(orm_template):
logger.notifyChannel('orm', netsvc.LOG_ERROR, 'create a column parent_left on object %s: fields.integer(\'Left Parent\', select=1)' % (self._table, ))
if 'parent_right' not in self._columns:
logger.notifyChannel('orm', netsvc.LOG_ERROR, 'create a column parent_right on object %s: fields.integer(\'Right Parent\', select=1)' % (self._table, ))
if self._columns[self._parent_name].ondelete<>'cascade':
if self._columns[self._parent_name].ondelete != 'cascade':
logger.notifyChannel('orm', netsvc.LOG_ERROR, "The column %s on object %s must be set as ondelete='cascade'" % (self._parent_name, self._name))
cr.execute('ALTER TABLE "%s" ADD COLUMN "parent_left" INTEGER' % (self._table,))
cr.execute('ALTER TABLE "%s" ADD COLUMN "parent_right" INTEGER' % (self._table,))
@ -3098,6 +3105,24 @@ class orm(orm_template):
self.pool.get('ir.model.access').check(cr, user, self._name, 'write', context=context)
# No direct update of parent_left/right
vals.pop('parent_left', None)
vals.pop('parent_right', None)
parents_changed = []
if self._parent_store and (self._parent_name in vals):
# The parent_left/right computation may take up to
# 5 seconds. No need to recompute the values if the
# parent is the same. Get the current value of the parent
base_query = 'SELECT id FROM %s WHERE id IN %%s AND %s' % \
(self._table, self._parent_name)
params = (tuple(ids),)
parent_val = vals[self._parent_name]
if parent_val:
cr.execute(base_query + " != %s", params + (parent_val,))
else:
cr.execute(base_query + " IS NULL", params)
parents_changed = map(operator.itemgetter(0), cr.fetchall())
upd0 = []
upd1 = []
@ -3187,41 +3212,48 @@ class orm(orm_template):
self.pool.get(table).write(cr, user, nids, v, context)
self._validate(cr, user, ids, context)
# TODO: use _order to set dest at the right position and not first node of parent
if self._parent_store and (self._parent_name in vals):
# TODO: use _order to set dest at the right position and not first node of parent
# We can't defer parent_store computation because the stored function
# fields that are computer may refer (directly or indirectly) to
# parent_left/right (via a child_of domain)
if parents_changed:
if self.pool._init:
self.pool._init_parent[self._name]=True
else:
for id in ids:
# Find Position of the element
if vals[self._parent_name]:
cr.execute('select parent_left,parent_right,id from '+self._table+' where '+self._parent_name+'=%s order by '+(self._parent_order or self._order), (vals[self._parent_name],))
else:
cr.execute('select parent_left,parent_right,id from '+self._table+' where '+self._parent_name+' is null order by '+(self._parent_order or self._order))
result_p = cr.fetchall()
position = None
for (pleft,pright,pid) in result_p:
if pid == id:
break
position = pright+1
order = self._parent_order or self._order
parent_val = vals[self._parent_name]
if parent_val:
clause, params = '%s=%%s' % (self._parent_name,), (parent_val,)
else:
clause, params = '%s IS NULL' % (self._parent_name,), ()
cr.execute('SELECT parent_right, id FROM %s WHERE %s ORDER BY %s' % (self._table, clause, order), params)
parents = cr.fetchall()
# It's the first node of the parent: position = parent_left+1
if not position:
if not vals[self._parent_name]:
position = 1
else:
cr.execute('select parent_left from '+self._table+' where id=%s', (vals[self._parent_name],))
position = cr.fetchone()[0]+1
# We have the new position !
cr.execute('select parent_left,parent_right from '+self._table+' where id=%s', (id,))
pleft,pright = cr.fetchone()
for id in parents_changed:
cr.execute('SELECT parent_left, parent_right FROM %s WHERE id=%%s' % (self._table,), (id,))
pleft, pright = cr.fetchone()
distance = pright - pleft + 1
if position>pleft and position<=pright:
# Find Position of the element
position = None
for (parent_pright, parent_id) in parents:
if parent_id == id:
break
position = parent_pright+1
# It's the first node of the parent
if not position:
if not parent_val:
position = 1
else:
cr.execute('select parent_left from '+self._table+' where id=%s', (parent_val,))
position = cr.fetchone()[0]+1
if pleft < position <= pright:
raise except_orm(_('UserError'), _('Recursivity Detected.'))
if pleft<position:
if pleft < position:
cr.execute('update '+self._table+' set parent_left=parent_left+%s where parent_left>=%s', (distance, position))
cr.execute('update '+self._table+' set parent_right=parent_right+%s where parent_right>=%s', (distance, position))
cr.execute('update '+self._table+' set parent_left=parent_left+%s, parent_right=parent_right+%s where parent_left>=%s and parent_left<%s', (position-pleft,position-pleft, pleft, pright))
@ -3402,7 +3434,7 @@ class orm(orm_template):
self.check_access_rule(cr, user, [id_new], 'create', context=context)
upd_todo.sort(lambda x, y: self._columns[x].priority-self._columns[y].priority)
if self._parent_store:
if self._parent_store and not context.get('defer_parent_store_computation'):
if self.pool._init:
self.pool._init_parent[self._name]=True
else: