diff --git a/bin/addons/__init__.py b/bin/addons/__init__.py index 4734b1adc55..43dd256055c 100644 --- a/bin/addons/__init__.py +++ b/bin/addons/__init__.py @@ -138,7 +138,7 @@ def get_module_path(module): if os.path.exists(opj(_ad, module)) or os.path.exists(opj(_ad, '%s.zip' % module)): return opj(_ad, module) - logger.notifyChannel('init', netsvc.LOG_WARNING, 'addon %s: module not found' % (module,)) + logger.notifyChannel('init', netsvc.LOG_WARNING, 'module %s: module not found' % (module,)) return False raise IOError, 'Module not found : %s' % module @@ -216,7 +216,7 @@ def create_graph(module_list, force=None): try: info = eval(tools.file_open(terp_file).read()) except: - logger.notifyChannel('init', netsvc.LOG_ERROR, 'addon %s: eval file %s' % (module, terp_file)) + logger.notifyChannel('init', netsvc.LOG_ERROR, 'module %s: eval file %s' % (module, terp_file)) raise if info.get('installable', True): packages.append((module, info.get('depends', []), info)) @@ -246,18 +246,25 @@ def create_graph(module_list, force=None): for package in later: unmet_deps = filter(lambda p: p not in graph, dependencies[package]) - logger.notifyChannel('init', netsvc.LOG_ERROR, 'addon %s: Unmet dependencies: %s' % (package, ', '.join(unmet_deps))) + logger.notifyChannel('init', netsvc.LOG_ERROR, 'module %s: Unmet dependencies: %s' % (package, ', '.join(unmet_deps))) return graph def init_module_objects(cr, module_name, obj_list): pool = pooler.get_pool(cr.dbname) - logger.notifyChannel('init', netsvc.LOG_INFO, 'addon %s: creating or updating database tables' % module_name) + logger.notifyChannel('init', netsvc.LOG_INFO, 'module %s: creating or updating database tables' % module_name) + todo = [] for obj in obj_list: if hasattr(obj, 'init'): obj.init(cr) - obj._auto_init(cr, {'module': module_name}) + result = obj._auto_init(cr, {'module': module_name}) + if result: + todo += result cr.commit() + todo.sort() + for t in todo: + t[1](cr, *t[2]) + cr.commit() # # Register module named m, if not already registered @@ -266,7 +273,7 @@ def register_class(m): global loaded if m in loaded: return - logger.notifyChannel('init', netsvc.LOG_INFO, 'addon %s: registering classes' % m) + logger.notifyChannel('init', netsvc.LOG_INFO, 'module %s: registering objects' % m) loaded.append(m) mod_path = get_module_path(m) if not os.path.isfile(mod_path+'.zip'): @@ -401,13 +408,13 @@ class MigrationManager(object): mod = None try: mod = imp.load_source(name, pyfile, fp) - logger.notifyChannel('migration', netsvc.LOG_INFO, 'addon %(addon)s: Running migration %(version)s %(name)s"' % mergedict({'name': mod.__name__},strfmt)) + logger.notifyChannel('migration', netsvc.LOG_INFO, 'module %(addon)s: Running migration %(version)s %(name)s"' % mergedict({'name': mod.__name__},strfmt)) mod.migrate(self.cr, pkg.installed_version) except ImportError: - logger.notifyChannel('migration', netsvc.LOG_ERROR, 'addon %(addon)s: Unable to load %(stage)-migration file %(file)s' % mergedict({'file': opj(modulename,pyfile)}, strfmt)) + logger.notifyChannel('migration', netsvc.LOG_ERROR, 'module %(addon)s: Unable to load %(stage)-migration file %(file)s' % mergedict({'file': opj(modulename,pyfile)}, strfmt)) raise except AttributeError: - logger.notifyChannel('migration', netsvc.LOG_ERROR, 'addon %(addon)s: Each %(stage)-migration file must have a "migrate(cr, installed_version)" function' % strfmt) + logger.notifyChannel('migration', netsvc.LOG_ERROR, 'module %(addon)s: Each %(stage)-migration file must have a "migrate(cr, installed_version)" function' % strfmt) except: raise fp.close() @@ -444,6 +451,7 @@ def load_module_graph(cr, graph, status=None, check_access_rules=True, **kwargs) migrations = MigrationManager(cr, graph) + check_rules = False for package in graph: status['progress'] = (float(statusi)+0.1)/len(graph) m = package.name @@ -452,19 +460,20 @@ def load_module_graph(cr, graph, status=None, check_access_rules=True, **kwargs) migrations.migrate_module(package, 'pre') register_class(m) - logger.notifyChannel('init', netsvc.LOG_INFO, 'addon %s' % m) + logger.notifyChannel('init', netsvc.LOG_INFO, 'module %s loading objects' % m) modules = pool.instanciate(m, cr) idref = {} status['progress'] = (float(statusi)+0.4)/len(graph) if hasattr(package, 'init') or hasattr(package, 'update') or package.state in ('to install', 'to upgrade'): + check_rules = True init_module_objects(cr, m, modules) for kind in ('init', 'update'): for filename in package.data.get('%s_xml' % kind, []): mode = 'update' if hasattr(package, 'init') or package.state=='to install': mode = 'init' - logger.notifyChannel('init', netsvc.LOG_INFO, 'addon %s: loading %s' % (m, filename)) + logger.notifyChannel('init', netsvc.LOG_INFO, 'module %s: loading %s' % (m, filename)) name, ext = os.path.splitext(filename) fp = tools.file_open(opj(m, filename)) if ext == '.csv': @@ -482,7 +491,7 @@ def load_module_graph(cr, graph, status=None, check_access_rules=True, **kwargs) status['progress'] = (float(statusi)+0.75)/len(graph) for xml in package.data.get('demo_xml', []): name, ext = os.path.splitext(xml) - logger.notifyChannel('init', netsvc.LOG_INFO, 'addon %s: loading %s' % (m, xml)) + logger.notifyChannel('init', netsvc.LOG_INFO, 'module %s: loading %s' % (m, xml)) fp = tools.file_open(opj(m, xml)) if ext == '.csv': tools.convert_csv_import(cr, m, os.path.basename(xml), fp.read(), idref, noupdate=True) @@ -503,16 +512,14 @@ def load_module_graph(cr, graph, status=None, check_access_rules=True, **kwargs) if modobj: modobj.update_translations(cr, 1, [mid], None) cr.commit() - - migrations.migrate_module(package, 'post') statusi+=1 - if check_access_rules: + if check_access_rules and check_rules: cr.execute("""select model,name from ir_model where id not in (select model_id from ir_model_access)""") for (model,name) in cr.fetchall(): - logger.notifyChannel('init', netsvc.LOG_WARNING, 'addon object %s (%s) has no access rules!' % (model,name)) + logger.notifyChannel('init', netsvc.LOG_WARNING, 'object %s (%s) has no access rules!' % (model,name)) pool = pooler.get_pool(cr.dbname) @@ -535,9 +542,12 @@ def load_modules(db, force_demo=False, status=None, update_module=False): if update_module: basegraph = create_graph(['base'], force) load_module_graph(cr, basegraph, status, check_access_rules=False, report=report) - + modobj = pool.get('ir.module.module') - modobj.update_list(cr, 1) + logger.notifyChannel('init', netsvc.LOG_INFO, 'updating modules list') + cr.execute("select id from ir_module_module where state in ('to install','to upgrade') and name=%s", ('base',)) + if cr.rowcount: + modobj.update_list(cr, 1) mods = [k for k in tools.config['init'] if tools.config['init'][k]] if mods: @@ -547,25 +557,27 @@ def load_modules(db, force_demo=False, status=None, update_module=False): mods = [k for k in tools.config['update'] if tools.config['update'][k]] if mods: - ids = modobj.search(cr, 1, ['&', '&',('state', '=', 'installed'), ('name', 'in', mods), '!', ('name', '=', 'base')]) + ids = modobj.search(cr, 1, ['&',('state', '=', 'installed'), ('name', 'in', mods)]) if ids: modobj.button_upgrade(cr, 1, ids) - cr.execute("select name from ir_module_module where state in ('installed', 'to install', 'to upgrade','to remove')") + cr.execute("update ir_module_module set state=%s where name=%s", ('installed', 'base')) + cr.execute("select name from ir_module_module where state in ('installed', 'to install', 'to upgrade')") else: - cr.execute("select name from ir_module_module where state in ('installed', 'to upgrade', 'to remove')") + cr.execute("select name from ir_module_module where state in ('installed', 'to upgrade')") module_list = [name for (name,) in cr.fetchall()] graph = create_graph(module_list, force) # the 'base' module has already been updated base = graph['base'] + base.state = 'installed' for kind in ('init', 'demo', 'update'): if hasattr(base, kind): delattr(base, kind) load_module_graph(cr, graph, status, report=report) if report.get_report(): - logger.notifyChannel('init', netsvc.LOG_INFO, 'assert: %s' % report) + logger.notifyChannel('init', netsvc.LOG_INFO, report) for kind in ('init', 'demo', 'update'): tools.config[kind]={} @@ -577,29 +589,29 @@ def load_modules(db, force_demo=False, status=None, update_module=False): pool = pooler.get_pool(cr.dbname) cr.execute('select model,res_id from ir_model_data where not noupdate and module=%s order by id desc', (mod_name,)) for rmod,rid in cr.fetchall(): - # - # TO BE Improved: - # I can not use the class_pool has _table could be defined in __init__ - # and I can not use the pool has the module could not be loaded in the pool - # uid = 1 pool.get(rmod).unlink(cr, uid, [rid]) cr.commit() # # TODO: remove menu without actions of childs # - cr.execute('''delete from - ir_ui_menu - where - (id not in (select parent_id from ir_ui_menu where parent_id is not null)) - and - (id not in (select res_id from ir_values where model='ir.ui.menu')) - and - (id not in (select res_id from ir_model_data where model='ir.ui.menu'))''') + while True: + cr.execute('''delete from + ir_ui_menu + where + (id not in (select parent_id from ir_ui_menu where parent_id is not null)) + and + (id not in (select res_id from ir_values where model='ir.ui.menu')) + and + (id not in (select res_id from ir_model_data where model='ir.ui.menu'))''') + if not cr.rowcount: + break + else: + logger.notifyChannel('init', netsvc.LOG_INFO, 'removed %d unused menus' % (cr.rowcount,)) cr.execute("update ir_module_module set state=%s where state in ('to remove')", ('uninstalled', )) cr.commit() - pooler.restart_pool(cr.dbname) + #pooler.restart_pool(cr.dbname) cr.close() diff --git a/bin/addons/base/ir/ir_attachment.py b/bin/addons/base/ir/ir_attachment.py index fd44da84d72..da603202a1a 100644 --- a/bin/addons/base/ir/ir_attachment.py +++ b/bin/addons/base/ir/ir_attachment.py @@ -25,17 +25,15 @@ from osv.orm import except_orm import tools class ir_attachment(osv.osv): - def check(self, cr, uid, ids, mode): if not ids: return ima = self.pool.get('ir.model.access') if isinstance(ids, (int, long)): ids = [ids] - objs = self.browse(cr, uid, ids) or [] - for o in objs: - if o and o.res_model: - ima.check(cr, uid, o.res_model, mode) + cr.execute('select distinct res_model from ir_attachment where id in ('+','.join(map(str, ids))+')') + for obj in cr.fetchall(): + ima.check(cr, uid, obj[0], mode) def search(self, cr, uid, args, offset=0, limit=None, order=None, context=None, count=False): diff --git a/bin/addons/base/module/module.py b/bin/addons/base/module/module.py index 2fb77c926f0..439cf5b57a6 100644 --- a/bin/addons/base/module/module.py +++ b/bin/addons/base/module/module.py @@ -122,15 +122,19 @@ class module(osv.osv): view_id = model_data_obj.search(cr,uid,[('module','in', mnames.keys()), ('model','in',('ir.ui.view','ir.actions.report.xml','ir.ui.menu'))]) for data_id in model_data_obj.browse(cr,uid,view_id,context): - key = data_id['model'] - if key=='ir.ui.view': - v = view_obj.browse(cr,uid,data_id.res_id) - aa = v.inherit_id and '* INHERIT ' or '' - res[mnames[data_id.module]]['views_by_module'] += aa + v.name + ' ('+v.type+')\n' - elif key=='ir.actions.report.xml': - res[mnames[data_id.module]]['reports_by_module'] += report_obj.browse(cr,uid,data_id.res_id).name + '\n' - elif key=='ir.ui.menu': - res[mnames[data_id.module]]['menus_by_module'] += menu_obj.browse(cr,uid,data_id.res_id).complete_name + '\n' + # We use try except, because views or menus may not exist + try: + key = data_id['model'] + if key=='ir.ui.view': + v = view_obj.browse(cr,uid,data_id.res_id) + aa = v.inherit_id and '* INHERIT ' or '' + res[mnames[data_id.module]]['views_by_module'] += aa + v.name + ' ('+v.type+')\n' + elif key=='ir.actions.report.xml': + res[mnames[data_id.module]]['reports_by_module'] += report_obj.browse(cr,uid,data_id.res_id).name + '\n' + elif key=='ir.ui.menu': + res[mnames[data_id.module]]['menus_by_module'] += menu_obj.browse(cr,uid,data_id.res_id).complete_name + '\n' + except KeyError, e: + pass return res _columns = { diff --git a/bin/netsvc.py b/bin/netsvc.py index a0253c867da..1ab06841156 100644 --- a/bin/netsvc.py +++ b/bin/netsvc.py @@ -2,7 +2,7 @@ # -*- encoding: utf-8 -*- ############################################################################## # -# OpenERP, Open Source Management Solution +# OpenERP, Open Source Management Solution # Copyright (C) 2004-2008 Tiny SPRL (). All Rights Reserved # $Id$ # @@ -398,12 +398,14 @@ class TinySocketClientThread(threading.Thread): ts.mysend(r) except Exception, e: tb_s = reduce(lambda x, y: x+y, traceback.format_exception(sys.exc_type, sys.exc_value, sys.exc_traceback)) - s = str(e) + print e + print tb_s import tools if tools.config['debug_mode']: import pdb tb = sys.exc_info()[2] pdb.post_mortem(tb) + e = Exception(e.message) ts.mysend(e, exception=True, traceback=tb_s) except: pass diff --git a/bin/openerp-server.py b/bin/openerp-server.py index 05734f7fdf7..f52d8415d6d 100755 --- a/bin/openerp-server.py +++ b/bin/openerp-server.py @@ -107,10 +107,16 @@ import service #---------------------------------------------------------- # import addons #---------------------------------------------------------- + import addons -if tools.config['init'] or tools.config['update']: - pooler.get_db_and_pool(tools.config['db_name'], update_module=True) +#---------------------------------------------------------- +# Load and update databases if requested +#---------------------------------------------------------- + +if tools.config['db_name']: + for db in tools.config['db_name'].split(','): + pooler.get_db_and_pool(db, update_module=tools.config['init'] or tools.config['update']) #---------------------------------------------------------- # translation stuff diff --git a/bin/osv/fields.py b/bin/osv/fields.py index 390f6e2d802..c7bc9aed2fa 100644 --- a/bin/osv/fields.py +++ b/bin/osv/fields.py @@ -196,6 +196,7 @@ class binary(_column): _symbol_c = '%s' _symbol_f = lambda symb: symb and Binary(symb) or None _symbol_set = (_symbol_c, _symbol_f) + _symbol_get = lambda self, x: x and str(x) _classic_read = False @@ -208,7 +209,6 @@ class binary(_column): context = {} if not values: values = [] - res = {} for i in ids: val = None @@ -216,10 +216,10 @@ class binary(_column): if v['id'] == i: val = v[name] break - res.setdefault(i, val) if context.get('bin_size', False): res[i] = tools.human_size(val) - + else: + res[i] = val return res get = get_memory @@ -276,6 +276,9 @@ class many2one(_column): _classic_read = False _classic_write = True _type = 'many2one' + _symbol_c = '%s' + _symbol_f = lambda x: x or None + _symbol_set = (_symbol_c, _symbol_f) def __init__(self, obj, string='unknown', **args): _column.__init__(self, string=string, **args) diff --git a/bin/osv/orm.py b/bin/osv/orm.py index b1fbcd93522..6afb7006aa2 100644 --- a/bin/osv/orm.py +++ b/bin/osv/orm.py @@ -1376,10 +1376,31 @@ class orm(orm_template): browse_rec(None) return True + def _update_store(self, cr, f, k): + logger = netsvc.Logger() + logger.notifyChannel('init', netsvc.LOG_INFO, "storing computed values of fields.function '%s'" % (k,)) + ss = self._columns[k]._symbol_set + update_query = 'UPDATE "%s" SET "%s"=%s WHERE id=%%s' % (self._table, k, ss[0]) + cr.execute('select id from '+self._table) + ids_lst = map(lambda x: x[0], cr.fetchall()) + while ids_lst: + iids = ids_lst[:40] + ids_lst = ids_lst[40:] + res = f.get(cr, self, iids, k, 1, {}) + for key,val in res.items(): + if f._multi: + val = val[k] + # if val is a many2one, just write the ID + if type(val)==tuple: + val = val[0] + if (val<>False) or (type(val)<>bool): + cr.execute(update_query, (ss[1](val), key)) + def _auto_init(self, cr, context={}): store_compute = False logger = netsvc.Logger() create = False + todo_end = [] self._field_create(cr, context=context) if not hasattr(self, "_auto") or self._auto: cr.execute("SELECT relname FROM pg_class WHERE relkind in ('r','v') AND relname='%s'" % self._table) @@ -1479,10 +1500,17 @@ class orm(orm_template): default = self._defaults[k](self, cr, 1, {}) ss = self._columns[k]._symbol_set query = 'UPDATE "%s" SET "%s"=%s' % (self._table, k, ss[0]) - cr.execute(query, (default is not None and ss[1](default) or None,)) + cr.execute(query, (ss[1](default),)) + cr.commit() + logger.notifyChannel('init', netsvc.LOG_DEBUG, 'setting default value of new column %s of table %s'% (k, self._table)) + elif not create: + logger.notifyChannel('init', netsvc.LOG_DEBUG, 'creating new column %s of table %s'% (k, self._table)) if isinstance(f, fields.function): - todo_update_store.append((f,k)) + order = 10 + if f.store is not True: + order = f.store[f.store.keys()[0]][2] + todo_update_store.append((order, f,k)) # and add constraints if needed if isinstance(f, fields.many2one): @@ -1497,10 +1525,10 @@ class orm(orm_template): if f.select: cr.execute('CREATE INDEX "%s_%s_index" ON "%s" ("%s")' % (self._table, k, self._table, k)) if f.required: - cr.commit() try: + cr.commit() cr.execute('ALTER TABLE "%s" ALTER COLUMN "%s" SET NOT NULL' % (self._table, k)) - except: + except Exception, e: logger.notifyChannel('init', netsvc.LOG_WARNING, 'WARNING: unable to set column %s of table %s not null !\nTry to re-run: openerp-server.py --update=module\nIf it doesn\'t work, update records and execute manually:\nALTER TABLE %s ALTER COLUMN %s SET NOT NULL' % (k, self._table, self._table, k)) cr.commit() elif len(res)==1: @@ -1509,40 +1537,40 @@ class orm(orm_template): f_pg_size = f_pg_def['size'] f_pg_notnull = f_pg_def['attnotnull'] if isinstance(f, fields.function) and not f.store: - logger.notifyChannel('init', netsvc.LOG_WARNING, 'column %s (%s) in table %s was converted to a function !\nYou should remove this column from your database.' % (k, f.string, self._table)) + logger.notifyChannel('init', netsvc.LOG_INFO, 'column %s (%s) in table %s was converted to a function !\nYou should remove this column from your database.' % (k, f.string, self._table)) f_obj_type = None else: f_obj_type = get_pg_type(f) and get_pg_type(f)[0] if f_obj_type: - if f_pg_type != f_obj_type: - logger.notifyChannel('init', netsvc.LOG_WARNING, "column '%s' in table '%s' has changed type (DB = %s, def = %s) !" % (k, self._table, f_pg_type, f._type)) + ok = False + casts = [ + ('text', 'char', 'VARCHAR(%d)' % (f.size or 0,), '::VARCHAR(%d)'%(f.size or 0,)), + ('varchar', 'text', 'TEXT', ''), + ('int4', 'float', get_pg_type(f)[1], '::'+get_pg_type(f)[1]), + ('date', 'datetime', 'TIMESTAMP', '::TIMESTAMP'), + ] if f_pg_type == 'varchar' and f._type == 'char' and f_pg_size != f.size: - # columns with the name 'type' cannot be changed for an unknown reason?! - if k != 'type': - if f_pg_size > f.size: - logger.notifyChannel('init', netsvc.LOG_WARNING, "column '%s' in table '%s' has changed size (DB = %d, def = %d), DB size will be kept !" % (k, self._table, f_pg_size, f.size)) - # If actual DB size is < than new - # We update varchar size, otherwise, we keep DB size - # to avoid truncated string... - if f_pg_size < f.size: - cr.execute('ALTER TABLE "%s" RENAME COLUMN "%s" TO temp_change_size' % (self._table, k)) - cr.execute('ALTER TABLE "%s" ADD COLUMN "%s" VARCHAR(%d)' % (self._table, k, f.size)) - cr.execute('UPDATE "%s" SET "%s"=temp_change_size::VARCHAR(%d)' % (self._table, k, f.size)) - cr.execute('ALTER TABLE "%s" DROP COLUMN temp_change_size' % (self._table,)) - cr.commit() - if f_pg_type == 'varchar' and f._type == 'text': - cr.execute("ALTER TABLE \"%s\" RENAME COLUMN \"%s\" TO temp_change_type" % (self._table, k)) - cr.execute("ALTER TABLE \"%s\" ADD COLUMN \"%s\" text " % (self._table, k)) - cr.execute("UPDATE \"%s\" SET \"%s\"=temp_change_type" % (self._table, k)) - cr.execute("ALTER TABLE \"%s\" DROP COLUMN temp_change_type" % (self._table,)) - cr.commit() - if f_pg_type == 'date' and f._type == 'datetime': - cr.execute('ALTER TABLE "%s" RENAME COLUMN "%s" TO temp_change_type' % (self._table, k)) - cr.execute('ALTER TABLE "%s" ADD COLUMN "%s" TIMESTAMP' % (self._table, k)) - cr.execute('UPDATE "%s" SET "%s"=temp_change_type::TIMESTAMP' % (self._table, k)) - cr.execute('ALTER TABLE "%s" DROP COLUMN temp_change_type' % (self._table,)) - cr.commit() + logger.notifyChannel('init', netsvc.LOG_INFO, "column '%s' in table '%s' changed size" % (k, self._table)) + cr.execute('ALTER TABLE "%s" RENAME COLUMN "%s" TO temp_change_size' % (self._table, k)) + cr.execute('ALTER TABLE "%s" ADD COLUMN "%s" VARCHAR(%d)' % (self._table, k, f.size)) + cr.execute('UPDATE "%s" SET "%s"=temp_change_size::VARCHAR(%d)' % (self._table, k, f.size)) + cr.execute('ALTER TABLE "%s" DROP COLUMN temp_change_size' % (self._table,)) + cr.commit() + for c in casts: + if (f_pg_type==c[0]) and (f._type==c[1]): + logger.notifyChannel('init', netsvc.LOG_INFO, "column '%s' in table '%s' changed type to %s." % (k, self._table, c[1])) + ok = True + cr.execute('ALTER TABLE "%s" RENAME COLUMN "%s" TO temp_change_size' % (self._table, k)) + cr.execute('ALTER TABLE "%s" ADD COLUMN "%s" %s' % (self._table, k, c[2])) + cr.execute(('UPDATE "%s" SET "%s"=temp_change_size'+c[3]) % (self._table, k)) + cr.execute('ALTER TABLE "%s" DROP COLUMN temp_change_size CASCADE' % (self._table,)) + cr.commit() + + if f_pg_type != f_obj_type: + if not ok: + logger.notifyChannel('init', netsvc.LOG_WARNING, "column '%s' in table '%s' has changed type (DB = %s, def = %s) but unable to migrate this change !" % (k, self._table, f_pg_type, f._type)) + # if the field is required and hasn't got a NOT NULL constraint if f.required and f_pg_notnull == 0: # set the field to the default value if any @@ -1552,12 +1580,12 @@ class orm(orm_template): ss = self._columns[k]._symbol_set query = 'UPDATE "%s" SET "%s"=%s WHERE %s is NULL' % (self._table, k, ss[0], k) cr.execute(query, (ss[1](default),)) - cr.commit() # add the NOT NULL constraint + cr.commit() try: cr.execute('ALTER TABLE "%s" ALTER COLUMN "%s" SET NOT NULL' % (self._table, k)) cr.commit() - except: + except Exception, e: logger.notifyChannel('init', netsvc.LOG_WARNING, 'unable to set a NOT NULL constraint on column %s of the %s table !\nIf you want to have it, you should update the records and execute manually:\nALTER TABLE %s ALTER COLUMN %s SET NOT NULL' % (k, self._table, self._table, k)) cr.commit() elif not f.required and f_pg_notnull == 1: @@ -1606,23 +1634,8 @@ class orm(orm_template): else: logger = netsvc.Logger() logger.notifyChannel('orm', netsvc.LOG_ERROR, "Programming error !") - for f,k in todo_update_store: - ss = self._columns[k]._symbol_set - update_query = 'UPDATE "%s" SET "%s"=%s WHERE id=%%s' % (self._table, k, ss[0]) - cr.execute('select id from '+self._table) - ids_lst = map(lambda x: x[0], cr.fetchall()) - while ids_lst: - iids = ids_lst[:40] - ids_lst = ids_lst[40:] - res = f.get(cr, self, iids, k, 1, {}) - for key,val in res.items(): - if f._multi: - val = val[k] - if (val<>False) or (type(val)<>bool): - #cr.execute("UPDATE \"%s\" SET \"%s\"='%s' where id=%d"% (self._table, k, val, key)) - cr.execute(update_query, (ss[1](val), key)) - #else: - # cr.execute("UPDATE \"%s\" SET \"%s\"=NULL where id=%d"% (self._table, k, key)) + for order,f,k in todo_update_store: + todo_end.append((order, self._update_store, (f, k))) else: cr.execute("SELECT relname FROM pg_class WHERE relkind in ('r','v') AND relname=%s", (self._table,)) @@ -1647,6 +1660,7 @@ class orm(orm_template): cr.commit() if store_compute: self._parent_store_compute(cr) + return todo_end def __init__(self, cr): super(orm, self).__init__(cr) @@ -1658,18 +1672,15 @@ class orm(orm_template): if not f.store: continue if self._columns[store_field].store is True: - sm = {self._name:(lambda self,cr, uid, ids, c={}: ids, None)} + sm = {self._name:(lambda self,cr, uid, ids, c={}: ids, None, 10)} else: sm = self._columns[store_field].store for object, aa in sm.items(): - if len(aa)==2: - (fnct,fields2)=aa - order = 1 - elif len(aa)==3: + if len(aa)==3: (fnct,fields2,order)=aa else: - raise except_orm(_('Error'), - _('Invalid function definition %s in object %s !' % (store_field, self._name))) + raise except_orm('Error', + ('Invalid function definition %s in object %s !\nYou must use the definition: store={object:(fnct, fields, priority)}.' % (store_field, self._name))) self.pool._store_function.setdefault(object, []) ok = True for x,y,z,e,f in self.pool._store_function[object]: @@ -1790,7 +1801,6 @@ class orm(orm_template): value[key[8:]] = context[key] return value - # # Update objects that uses this one to update their _inherits fields # @@ -2402,16 +2412,22 @@ class orm(orm_template): def _store_set_values(self, cr, uid, ids, fields, context): todo = {} + keys = [] for f in fields: + if self._columns[f]._multi not in keys: + keys.append(self._columns[f]._multi) todo.setdefault(self._columns[f]._multi, []) todo[self._columns[f]._multi].append(f) - for key,val in todo.items(): + for key in keys: + val = todo[key] if key: result = self._columns[val[0]].get(cr, self, ids, val, uid, context=context) for id,value in result.items(): upd0 = [] upd1 = [] for v in value: + if v not in val: + continue if self._columns[v]._type in ('many2one', 'one2one'): try: value[v] = value[v][0] @@ -2433,7 +2449,7 @@ class orm(orm_template): except: pass cr.execute('update "' + self._table + '" set ' + \ - '"'+f+'"='+self._columns[f]._symbol_set[0] + ' where id = %s', (value,id)) + '"'+f+'"='+self._columns[f]._symbol_set[0] + ' where id = %s', (self._columns[f]._symbol_set[1](value),id)) return True # diff --git a/bin/osv/osv.py b/bin/osv/osv.py index 1650dbde900..64010c45636 100644 --- a/bin/osv/osv.py +++ b/bin/osv/osv.py @@ -184,7 +184,7 @@ class osv_memory(orm.orm_memory): name = hasattr(cls, '_name') and cls._name or cls._inherit parent_name = hasattr(cls, '_inherit') and cls._inherit if parent_name: - print 'Inherit not supported in osv_memory object !' + raise 'Inherit not supported in osv_memory object !' obj = object.__new__(cls) obj.__init__(pool, cr) return obj diff --git a/bin/report/report_sxw.py b/bin/report/report_sxw.py index 416db51fcc5..ddf0393e910 100644 --- a/bin/report/report_sxw.py +++ b/bin/report/report_sxw.py @@ -610,7 +610,6 @@ class report_sxw(report_rml): attach = report_xml.attachment rml = report_xml.report_rml_content report_type = report_xml.report_type - context['actual_model']=report_xml.actual_model else: ir_menu_report_obj = pool.get('ir.ui.menu') report_menu_ids = ir_menu_report_obj.search(cr, uid, diff --git a/bin/service/web_services.py b/bin/service/web_services.py index d6792c54b9f..07fdd7412f9 100644 --- a/bin/service/web_services.py +++ b/bin/service/web_services.py @@ -29,7 +29,6 @@ import logging import threading, thread import time -import base64 import addons import sql_db diff --git a/bin/sql_db.py b/bin/sql_db.py index e88c6b12efb..08b6a25da79 100644 --- a/bin/sql_db.py +++ b/bin/sql_db.py @@ -26,6 +26,7 @@ from psycopg2.pool import ThreadedConnectionPool from psycopg2.psycopg1 import cursor as psycopg1cursor import psycopg2.extensions + psycopg2.extensions.register_type(psycopg2.extensions.UNICODE) types_mapping = { @@ -34,6 +35,10 @@ types_mapping = { 'datetime': (1114,), } +def unbuffer(symb, cr): + if symb is None: return None + return str(symb) + def undecimalize(symb, cr): if symb is None: return None return float(symb) diff --git a/bin/tools/config.py b/bin/tools/config.py index 34434086610..224ac5e4e72 100644 --- a/bin/tools/config.py +++ b/bin/tools/config.py @@ -35,7 +35,7 @@ class configmanager(object): 'netport': '8070', 'db_host': False, 'db_port': False, - 'db_name': 'terp', + 'db_name': False, 'db_user': False, 'db_password': False, 'db_maxconn': 64, diff --git a/bin/tools/convert.py b/bin/tools/convert.py index 8e5078985c8..aa24ea03cc2 100644 --- a/bin/tools/convert.py +++ b/bin/tools/convert.py @@ -663,7 +663,7 @@ form: module.record_id""" % (xml_id,) # if not rec_id and not self.isnoupdate(data_node): # print "Warning", rec_model - if self.isnoupdate(data_node) and not self.mode == 'init': + if self.isnoupdate(data_node) and not self.mode in ('init','update'): # check if the xml record has an id string if rec_id: id = self.pool.get('ir.model.data')._update_dummy(cr, self.uid, rec_model, self.module, rec_id) @@ -724,10 +724,11 @@ form: module.record_id""" % (xml_id,) if isinstance(model._columns[f_name], osv.fields.integer): f_val = int(f_val) res[f_name] = f_val + id = self.pool.get('ir.model.data')._update(cr, self.uid, rec_model, self.module, res, rec_id or False, not self.isnoupdate(data_node), noupdate=self.isnoupdate(data_node), mode=self.mode ) if rec_id: self.idref[rec_id] = int(id) - if config.get('import_partial', False): + if config.get('i mport_partial', False): cr.commit() return rec_model, id diff --git a/bin/workflow/wkf_service.py b/bin/workflow/wkf_service.py index 598bf8ac9cf..1a7be33700c 100644 --- a/bin/workflow/wkf_service.py +++ b/bin/workflow/wkf_service.py @@ -44,7 +44,7 @@ class workflow_service(netsvc.Service): def trg_write(self, uid, res_type, res_id, cr): ident = (uid,res_type,res_id) - cr.execute('select id from wkf_instance where res_id=%s and res_type=%s and state=%s', (res_id,res_type, 'active')) + cr.execute('select id from wkf_instance where res_id=%s and res_type=%s and state=%s', (res_id or None,res_type or None, 'active')) for (id,) in cr.fetchall(): instance.update(cr, id, ident)