Speed Improvement:
Nested Trees New Domains Bugfixes Compute multiple function fields at once (multi) bzr revid: fp@tinyerp.com-20080817182829-dc60s4srja6ck0bw
This commit is contained in:
parent
61d07d0771
commit
d88fb99fe4
|
@ -270,25 +270,26 @@ def load_module_graph(cr, graph, status=None, **kwargs):
|
|||
cr.execute('update ir_module_module set demo=%s where name=%s', (True, package.name))
|
||||
package_todo.append(package.name)
|
||||
cr.execute("update ir_module_module set state='installed' where state in ('to upgrade', 'to install') and name=%s", (package.name,))
|
||||
|
||||
# check if all model of the module have at least a access rule.
|
||||
cr.execute(""" SELECT name
|
||||
FROM ir_model m
|
||||
WHERE EXISTS (SELECT 1
|
||||
FROM ir_model_data
|
||||
WHERE module = %s
|
||||
AND model = m.name
|
||||
)
|
||||
AND NOT EXISTS (SELECT 1
|
||||
FROM ir_model_access
|
||||
WHERE model_id = m.id
|
||||
)
|
||||
""", (m,))
|
||||
|
||||
for (model,) in cr.fetchall():
|
||||
logger.notifyChannel('init', netsvc.LOG_WARNING, 'addon:%s:object %s has no access rules!' % (m,model,))
|
||||
# check if all model of the module have at least a access rule.
|
||||
# TODO: improve this query which is very slow !!!
|
||||
cr.execute(""" SELECT name
|
||||
FROM ir_model m
|
||||
WHERE EXISTS (SELECT 1
|
||||
FROM ir_model_data
|
||||
WHERE module = %s
|
||||
AND model = m.name
|
||||
)
|
||||
AND NOT EXISTS (SELECT 1
|
||||
FROM ir_model_access
|
||||
WHERE model_id = m.id
|
||||
)
|
||||
""", (m,))
|
||||
|
||||
cr.commit()
|
||||
for (model,) in cr.fetchall():
|
||||
logger.notifyChannel('init', netsvc.LOG_WARNING, 'addon:%s:object %s has no access rules!' % (m,model,))
|
||||
|
||||
cr.commit()
|
||||
statusi+=1
|
||||
|
||||
pool = pooler.get_pool(cr.dbname)
|
||||
|
|
|
@ -17,12 +17,11 @@ class expression(object):
|
|||
and element in ['&', '|', '!']
|
||||
|
||||
def _is_leaf(self, element):
|
||||
return isinstance(element, tuple) \
|
||||
return (isinstance(element, tuple) or isinstance(element, list)) \
|
||||
and len(element) == 3 \
|
||||
and element[1] in ('=', '!=', '<>', '<=', '<', '>', '>=', '=like', 'like', 'not like', 'ilike', 'not ilike', 'in', 'not in', 'child_of')
|
||||
and element[1] in ('=', '!=', '<>', '<=', '<', '>', '>=', '=like', 'like', 'not like', 'ilike', 'not ilike', 'in', 'not in', 'child_of', 'inselect')
|
||||
|
||||
def __execute_recursive_in(self, cr, s, f, w, ids):
|
||||
#deprecated -> use _left and _right...
|
||||
res = []
|
||||
for i in range(0, len(ids), cr.IN_MAX):
|
||||
subids = ids[i:i+cr.IN_MAX]
|
||||
|
@ -50,23 +49,30 @@ class expression(object):
|
|||
if not self.__exp:
|
||||
return self
|
||||
|
||||
def _rec_get(ids, table, parent):
|
||||
if table._parent_store:
|
||||
def _rec_get(ids, table, parent, left='id', prefix=''):
|
||||
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)]
|
||||
doms = []
|
||||
for o in table.browse(cr, uid, ids, context=context):
|
||||
if doms:
|
||||
doms.insert(0,'|')
|
||||
doms += ['&',('parent_left','<',o.parent_right),('parent_left','>=',o.parent_left)]
|
||||
return table.search(cr, uid, doms, context=context)
|
||||
if prefix:
|
||||
return [(left, 'in', table.search(cr, uid, doms, context=context))]
|
||||
return doms
|
||||
else:
|
||||
if not ids:
|
||||
return []
|
||||
ids2 = table.search(cr, uid, [(parent, 'in', ids)], context=context)
|
||||
return ids + _rec_get(ids2, table, parent)
|
||||
return [(prefix+left, 'in', ids2+ids)]
|
||||
|
||||
self.__main_table = table
|
||||
|
||||
for i, e in enumerate(self.__exp):
|
||||
i = -1
|
||||
while i+1<len(self.__exp):
|
||||
i+=1
|
||||
e = self.__exp[i]
|
||||
if self._is_operator(e) or e == self.__DUMMY_LEAF:
|
||||
continue
|
||||
left, operator, right = e
|
||||
|
@ -83,8 +89,8 @@ class expression(object):
|
|||
field = working_table._columns.get(fargs[0], False)
|
||||
if not field:
|
||||
if left == 'id' and operator == 'child_of':
|
||||
right += _rec_get(right, working_table, working_table._parent_name)
|
||||
self.__exp[i] = ('id', 'in', right)
|
||||
dom = _rec_get(right, working_table, working_table._parent_name)
|
||||
self.__exp = self.__exp[:i] + dom + self.__exp[i+1:]
|
||||
continue
|
||||
|
||||
field_obj = table.pool.get(field._obj)
|
||||
|
@ -152,11 +158,10 @@ class expression(object):
|
|||
|
||||
self.__operator = 'in'
|
||||
if field._obj != working_table._name:
|
||||
right = ids2 + _rec_get(ids2, field_obj, working_table._parent_name)
|
||||
dom = _rec_get(ids2, field_obj, working_table._parent_name, left=left, prefix=left+'.')
|
||||
else:
|
||||
right = ids2 + _rec_get(ids2, working_table, left)
|
||||
left = 'id'
|
||||
self.__exp[i] = (left, 'in', right)
|
||||
dom = _rec_get(ids2, working_table, left)
|
||||
self.__exp = self.__exp[:i] + dom + self.__exp[i+1:]
|
||||
else:
|
||||
if isinstance(right, basestring):
|
||||
res_ids = field_obj.name_search(cr, uid, right, [], operator)
|
||||
|
|
|
@ -63,6 +63,7 @@ class _column(object):
|
|||
_properties = False
|
||||
_type = 'unknown'
|
||||
_obj = None
|
||||
_multi = False
|
||||
_symbol_c = '%s'
|
||||
_symbol_f = _symbol_set
|
||||
_symbol_set = (_symbol_c, _symbol_f)
|
||||
|
@ -553,13 +554,17 @@ class function(_column):
|
|||
_type = 'function'
|
||||
_properties = True
|
||||
|
||||
def __init__(self, fnct, arg=None, fnct_inv=None, fnct_inv_arg=None, type='float', fnct_search=None, obj=None, method=False, store=False, **args):
|
||||
#
|
||||
# multi: compute several fields in one call
|
||||
#
|
||||
def __init__(self, fnct, arg=None, fnct_inv=None, fnct_inv_arg=None, type='float', fnct_search=None, obj=None, method=False, store=False, multi=False, **args):
|
||||
_column.__init__(self, **args)
|
||||
self._obj = obj
|
||||
self._method = method
|
||||
self._fnct = fnct
|
||||
self._fnct_inv = fnct_inv
|
||||
self._arg = arg
|
||||
self._multi = multi
|
||||
if 'relation' in args:
|
||||
self._obj = args['relation']
|
||||
self._fnct_inv_arg = fnct_inv_arg
|
||||
|
@ -585,12 +590,10 @@ class function(_column):
|
|||
if not values:
|
||||
values = {}
|
||||
res = {}
|
||||
table = obj._table
|
||||
if self._method:
|
||||
# TODO get HAS to receive uid for permissions !
|
||||
return self._fnct(obj, cr, user, ids, name, self._arg, context)
|
||||
else:
|
||||
return self._fnct(cr, table, ids, name, self._arg, context)
|
||||
return self._fnct(cr, obj._table, ids, name, self._arg, context)
|
||||
|
||||
def set(self, cr, obj, id, name, value, user=None, context=None):
|
||||
if not context:
|
||||
|
|
140
bin/osv/orm.py
140
bin/osv/orm.py
|
@ -1257,7 +1257,7 @@ class orm(orm_template):
|
|||
_log_access = True
|
||||
_table = None
|
||||
_protected = ['read','write','create','default_get','perm_read','unlink','fields_get','fields_view_get','search','name_get','distinct_field_get','name_search','copy','import_data','search_count']
|
||||
def __parent_store_compute(self, cr):
|
||||
def _parent_store_compute(self, cr):
|
||||
logger = netsvc.Logger()
|
||||
logger.notifyChannel('init', netsvc.LOG_INFO, 'Computing parent left and right for table %s...' % (self._table, ))
|
||||
def browse_rec(root, pos=0):
|
||||
|
@ -1375,7 +1375,7 @@ class orm(orm_template):
|
|||
if not default:
|
||||
cr.execute("UPDATE \"%s\" SET \"%s\"=NULL" % (self._table, k))
|
||||
else:
|
||||
cr.execute("UPDATE \"%s\" SET \"%s\"=%%s" % (self._table, k), (default,))
|
||||
cr.execute("UPDATE \"%s\" SET \"%s\"='%s'" % (self._table, k, default))
|
||||
if isinstance(f, fields.function):
|
||||
cr.execute('select id from '+self._table)
|
||||
ids_lst = map(lambda x: x[0], cr.fetchall())
|
||||
|
@ -1513,7 +1513,7 @@ class orm(orm_template):
|
|||
cr.execute(line2)
|
||||
cr.commit()
|
||||
if store_compute:
|
||||
self.__parent_store_compute(cr)
|
||||
self._parent_store_compute(cr)
|
||||
|
||||
def __init__(self, cr):
|
||||
super(orm, self).__init__(cr)
|
||||
|
@ -1758,11 +1758,33 @@ class orm(orm_template):
|
|||
|
||||
# all non inherited fields for which the attribute whose name is in load is False
|
||||
fields_post = filter(lambda x: x in self._columns and not getattr(self._columns[x], load), fields)
|
||||
|
||||
# Compute POST fields
|
||||
todo = {}
|
||||
for f in fields_post:
|
||||
# get the value of that field for all records/ids
|
||||
res2 = self._columns[f].get(cr, self, ids, f, user, context=context, values=res)
|
||||
for record in res:
|
||||
record[f] = res2[record['id']]
|
||||
todo.setdefault(self._columns[f]._multi, [])
|
||||
todo[self._columns[f]._multi].append(f)
|
||||
print 'TODO', todo
|
||||
for key,val in todo.items():
|
||||
if key:
|
||||
print '* KEY', key
|
||||
res2 = self._columns[val[0]].get(cr, self, ids, val, user, context=context, values=res)
|
||||
print '* KEY RES', res2, val, ids
|
||||
for pos in range(len(val)):
|
||||
for record in res:
|
||||
record[val[pos]] = res2[record['id']][pos]
|
||||
else:
|
||||
print 'KEY NOT', key
|
||||
for f in val:
|
||||
res2 = self._columns[f].get(cr, self, ids, f, user, context=context, values=res)
|
||||
for record in res:
|
||||
record[f] = res2[record['id']]
|
||||
|
||||
#for f in fields_post:
|
||||
# # get the value of that field for all records/ids
|
||||
# res2 = self._columns[f].get(cr, self, ids, f, user, context=context, values=res)
|
||||
# for record in res:
|
||||
# record[f] = res2[record['id']]
|
||||
|
||||
readonly = None
|
||||
for vals in res:
|
||||
|
@ -2052,47 +2074,50 @@ class orm(orm_template):
|
|||
|
||||
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:
|
||||
cr.execute('select parent_left,parent_right from '+self._table+' where id=%d', (vals[self._parent_name],))
|
||||
res = cr.fetchone()
|
||||
if res:
|
||||
pleft,pright = res
|
||||
if self._parent_store and (self._parent_name in vals):
|
||||
if self.pool._init:
|
||||
self.pool._init_parent[self._name]=True
|
||||
else:
|
||||
cr.execute('select max(parent_right),max(parent_right)+1 from '+self._table)
|
||||
pleft,pright = cr.fetchone()
|
||||
cr.execute('select parent_left,parent_right,id from '+self._table+' where id in ('+','.join(map(lambda x:'%d',ids))+')', ids)
|
||||
dest = pleft + 1
|
||||
for cleft,cright,cid in cr.fetchall():
|
||||
if cleft > pleft:
|
||||
treeshift = pleft - cleft + 1
|
||||
leftbound = pleft+1
|
||||
rightbound = cleft-1
|
||||
cwidth = cright-cleft+1
|
||||
leftrange = cright
|
||||
rightrange = pleft
|
||||
cr.execute('select parent_left,parent_right from '+self._table+' where id=%d', (vals[self._parent_name],))
|
||||
res = cr.fetchone()
|
||||
if res:
|
||||
pleft,pright = res
|
||||
else:
|
||||
treeshift = pleft - cright
|
||||
leftbound = cright + 1
|
||||
rightbound = pleft
|
||||
cwidth = cleft-cright-1
|
||||
leftrange = pleft+1
|
||||
rightrange = cleft
|
||||
cr.execute('UPDATE '+self._table+'''
|
||||
SET
|
||||
parent_left = CASE
|
||||
WHEN parent_left BETWEEN %d AND %d THEN parent_left + %d
|
||||
WHEN parent_left BETWEEN %d AND %d THEN parent_left + %d
|
||||
ELSE parent_left
|
||||
END,
|
||||
parent_right = CASE
|
||||
WHEN parent_right BETWEEN %d AND %d THEN parent_right + %d
|
||||
WHEN parent_right BETWEEN %d AND %d THEN parent_right + %d
|
||||
ELSE parent_right
|
||||
END
|
||||
WHERE
|
||||
parent_left<%d OR parent_right>%d;
|
||||
''', (leftbound,rightbound,cwidth,cleft,cright,treeshift,leftbound,rightbound,
|
||||
cwidth,cleft,cright,treeshift,leftrange,rightrange))
|
||||
cr.execute('select max(parent_right),max(parent_right)+1 from '+self._table)
|
||||
pleft,pright = cr.fetchone()
|
||||
cr.execute('select parent_left,parent_right,id from '+self._table+' where id in ('+','.join(map(lambda x:'%d',ids))+')', ids)
|
||||
dest = pleft + 1
|
||||
for cleft,cright,cid in cr.fetchall():
|
||||
if cleft > pleft:
|
||||
treeshift = pleft - cleft + 1
|
||||
leftbound = pleft+1
|
||||
rightbound = cleft-1
|
||||
cwidth = cright-cleft+1
|
||||
leftrange = cright
|
||||
rightrange = pleft
|
||||
else:
|
||||
treeshift = pleft - cright
|
||||
leftbound = cright + 1
|
||||
rightbound = pleft
|
||||
cwidth = cleft-cright-1
|
||||
leftrange = pleft+1
|
||||
rightrange = cleft
|
||||
cr.execute('UPDATE '+self._table+'''
|
||||
SET
|
||||
parent_left = CASE
|
||||
WHEN parent_left BETWEEN %d AND %d THEN parent_left + %d
|
||||
WHEN parent_left BETWEEN %d AND %d THEN parent_left + %d
|
||||
ELSE parent_left
|
||||
END,
|
||||
parent_right = CASE
|
||||
WHEN parent_right BETWEEN %d AND %d THEN parent_right + %d
|
||||
WHEN parent_right BETWEEN %d AND %d THEN parent_right + %d
|
||||
ELSE parent_right
|
||||
END
|
||||
WHERE
|
||||
parent_left<%d OR parent_right>%d;
|
||||
''', (leftbound,rightbound,cwidth,cleft,cright,treeshift,leftbound,rightbound,
|
||||
cwidth,cleft,cright,treeshift,leftrange,rightrange))
|
||||
|
||||
if 'read_delta' in context:
|
||||
del context['read_delta']
|
||||
|
@ -2206,16 +2231,19 @@ class orm(orm_template):
|
|||
self._validate(cr, user, [id_new], context)
|
||||
|
||||
if self._parent_store:
|
||||
parent = vals.get(self._parent_name, False)
|
||||
if parent:
|
||||
cr.execute('select parent_left from '+self._table+' where id=%d', (parent,))
|
||||
pleft = cr.fetchone()[0]
|
||||
if self.pool._init:
|
||||
self.pool._init_parent[self._name]=True
|
||||
else:
|
||||
cr.execute('select max(parent_right) from '+self._table)
|
||||
pleft = cr.fetchone()[0] or 0
|
||||
cr.execute('update '+self._table+' set parent_left=%d,parent_right=%d', (pleft+1,pleft+2))
|
||||
cr.execute('update '+self._table+' set parent_left=parent_left+2 where parent_left>%d', (pleft,))
|
||||
cr.execute('update '+self._table+' set parent_right=parent_right+2 where parent_right>%d', (pleft,))
|
||||
parent = vals.get(self._parent_name, False)
|
||||
if parent:
|
||||
cr.execute('select parent_left from '+self._table+' where id=%d', (parent,))
|
||||
pleft = cr.fetchone()[0]
|
||||
else:
|
||||
cr.execute('select max(parent_right) from '+self._table)
|
||||
pleft = cr.fetchone()[0] or 0
|
||||
cr.execute('update '+self._table+' set parent_left=%d,parent_right=%d', (pleft+1,pleft+2))
|
||||
cr.execute('update '+self._table+' set parent_left=parent_left+2 where parent_left>%d', (pleft,))
|
||||
cr.execute('update '+self._table+' set parent_right=parent_right+2 where parent_right>%d', (pleft,))
|
||||
|
||||
wf_service = netsvc.LocalService("workflow")
|
||||
wf_service.trg_create(user, self._name, id_new, cr)
|
||||
|
@ -2281,7 +2309,7 @@ class orm(orm_template):
|
|||
# records unless they were explicitely asked for
|
||||
if 'active' in self._columns and (active_test and context.get('active_test', True)):
|
||||
if args:
|
||||
args = ['&', ('active', '=', 1)] + args
|
||||
args.insert(0, ('active', '=', 1))
|
||||
else:
|
||||
args = [('active', '=', 1)]
|
||||
|
||||
|
|
|
@ -60,6 +60,8 @@ class osv_pool(netsvc.Service):
|
|||
self.created = []
|
||||
self._sql_error = {}
|
||||
self._store_function = {}
|
||||
self._init = True
|
||||
self._init_parent = {}
|
||||
netsvc.Service.__init__(self, 'object_proxy', audience='')
|
||||
self.joinGroup('web-services')
|
||||
self.exportMethod(self.exportedMethods)
|
||||
|
@ -68,6 +70,17 @@ class osv_pool(netsvc.Service):
|
|||
self.exportMethod(self.execute)
|
||||
self.exportMethod(self.execute_cr)
|
||||
|
||||
def init_set(self, cr, mode):
|
||||
if mode<>self._init:
|
||||
if mode:
|
||||
self._init_parent={}
|
||||
if not mode:
|
||||
for o in self._init_parent:
|
||||
self.get(o)._parent_store_compute(cr)
|
||||
self._init = mode
|
||||
return True
|
||||
return False
|
||||
|
||||
def execute_cr(self, cr, uid, obj, method, *args, **kw):
|
||||
try:
|
||||
object = pooler.get_pool(cr.dbname).get(obj)
|
||||
|
|
|
@ -54,6 +54,10 @@ def get_db_and_pool(db_name, force_demo=False, status=None, update_module=False)
|
|||
pool = osv.osv.osv_pool()
|
||||
pool_dic[db_name] = pool
|
||||
addons.load_modules(db, force_demo, status, update_module)
|
||||
cr = db.cursor()
|
||||
pool.init_set(cr, False)
|
||||
cr.commit()
|
||||
cr.close()
|
||||
|
||||
if not update_module:
|
||||
import report
|
||||
|
|
|
@ -59,7 +59,6 @@ class fake_cursor:
|
|||
self.dbname = dbname
|
||||
|
||||
def execute(self, sql, params=None):
|
||||
print sql, params
|
||||
if not params:
|
||||
params=()
|
||||
def base_string(s):
|
||||
|
|
Loading…
Reference in New Issue