Odoo中文社区可以通过以下三个域名访问:shine-it.net , odoocn.org,odoo.net.cn

原论坛用户的基本信息和发帖这里都予以保留,请注意:原论坛用户无需重新注册新用户,但是您的密码需要重置

开发人员可以登录gitter讨论组: http://gitter.im/odoo-china/Talk, 需要github账号

如果您登录系统碰到问题,请在微信公众号留言:

分享一个SQL trace 功能



  • SAP中有个SQL跟踪的功能对开发很有帮助,在Odoo中虽然可以启用SQL调试参数或者在数据库配置文件中启用SQL语句日志功能,但这些功能要么不能按用户帐号,模块或数据表(model)过滤,不是很方便。<br />参考OCA中的connector项目,做了一个简单的SQL trace 模块,贴出来分享一下。<br />[b]init.py[/b]<br /><br />import sqltrace<br />import sqltrace_hook<br />import res_users<br /><br />[b]openerp.py[/b]<br /><br />{<br />    'name': 'SQL trace',<br />    'version': '1.0',<br />    'author': 'xxx',<br />    'website': '',<br />    'category': 'xxxx',<br />    'sequence': 100,<br />    'summary': 'SQL trace',<br />    'images': [<br />            ],<br />    'depends': [<br />        'mail',<br />    ],<br />    'description': """<br />    SQL Trace<br />    """,<br />    'data': ['res_users_view.xml'<br />    ],<br />    'test': [<br />    ],<br />    'installable': True,<br />    'auto_install': False,<br />    'application': True,<br />}<br /><br />[b]sqltrace_hook.py[/b]<br /><br />from openerp.osv import orm<br />import datetime<br /><br /><br />_search_original = orm.BaseModel._search<br /><br /><br />def _search(self, cr, user, args, offset=0, limit=None, order=None, context=None, count=False, access_rights_uid=None):<br />    start = datetime.datetime.now()<br />    result = _search_original(self, cr, user, args, offset, limit, order, context, count, access_rights_uid)<br />    duration = datetime.datetime.now() - start<br />    if context:  # make sure context is ready<br />        sql_trace = context.get("sql_trace", False)  # default no trace<br />        sql_module = context.get("sql_module", 'Empty')  # in case global context not ready<br />        sql_model = context.get("sql_model", 'Empty')<br />        if sql_module == 'Empty':<br />            check_module = False<br />        elif not sql_module:    # leave module emtpy to trace all modules<br />            check_module = True<br />        else:<br />            check_module = self._module in sql_module<br />        if sql_model == 'Empty':<br />            check_model = False<br />        elif not sql_model:  # leave model empty to trace all models<br />            check_model = True<br />        else:<br />            check_model = self._name in sql_model<br />        if sql_trace and check_module and check_model:<br />            query = self._where_calc(cr, user, args, context=context)<br />            self._apply_ir_rules(cr, user, query, 'read', context=context)<br />            order_by = self._generate_order_by(order, query)<br />            from_clause, where_clause, where_clause_params = query.get_sql()<br />            where_str = where_clause and (" WHERE %s" % where_clause) or ''<br />            limit_str = limit and ' limit %d' % limit or ''<br />            offset_str = offset and ' offset %d' % offset or ''<br />            query_str = 'SELECT "%s".id FROM ' % self._table + from_clause + where_str + order_by + limit_str + offset_str<br />            cr.execute("""INSERT INTO sqltrace (module,model,statement,user_id,sql,parameters, result, duration, date_update)<br />                                VALUES (%s,%s, %s, %s,%s, %s, %s ,%s, (now() at time zone 'UTC'))""",<br />                                (self._module, self._name, 'select', user, query_str, reduce(lambda x, y: str(x)+' ,'+str(y),<br />                                where_clause_params or ['']), str(result or ['']), duration.seconds))<br />    return result<br />orm.BaseModel._search = _search<br /><br />[b]sqltrace.py[/b]<br />from openerp import models, fields, api, _<br /><br /><br />class SQLTrace(models.Model):<br />    """ workstation """<br />    _name = 'sqltrace'<br />    _description = 'SQL Trace'<br /><br />    module = fields.Char()<br />    model = fields.Char()<br />    statement = fields.Char()<br />    user_id = fields.Many2one('res.users')<br />    sql = fields.Text()<br />    parameters = fields.Text()<br />    result = fields.Text()<br />    date_update = fields.Datetime()<br />    duration = fields.Float()<br /><br />[b]res_users.py[/b]<br /><br />from openerp import models, fields, api, _<br /><br />class res_users(models.Model):<br />    _inherit = 'res.users'<br /><br />    context_sql_trace = fields.Boolean('Activate SQL Trace?')<br />    context_sql_module = fields.Char('Modules for SQL Trace')<br />    context_sql_model = fields.Char('Models for SQL Trace')<br /><br />res_users_view.xml<br /><openerp><br />    <data><br />        <record model="ir.ui.view" id="sqltrace_user_view"><br />            <field name="name">sqltrace.user.view.inherit</field><br />            <field name="model">res.users</field><br />            <field name="inherit_id" ref="base.view_users_form"/><br />            <field name="priority" eval="20"/><br />            <field name="arch" type="xml"><br />                <field name="tz" position="after"><br />                    <group string="SQL Trace" name="SQLTrace"><br />                        <field name="context_sql_trace"/><br />                        <field name="context_sql_module"/><br />                        <field name="context_sql_model"/><br />                    </group><br />                </field><br />            </field><br />        </record><br />    </data><br /></openerp><br /><br /><br />重点分享<br />1. 在用户表中增加的栏位以context_开头的话,就会被自动加到全局的context中,有缓存的作用<br />2. 因为_search会在context可用前被调用,所以需要判断context是否可用<br />3. 解析SQL语句内容的部分从原models.py中的_search抄过来的



  • SAP中有个SQL跟踪的功能对开发很有帮助,在Odoo中虽然可以启用SQL调试参数或者在数据库配置文件中启用SQL语句日志功能,但这些功能要么不能按用户帐号,模块或数据表(model)过滤,不是很方便。<br />参考OCA中的connector项目,做了一个简单的SQL trace 模块,贴出来分享一下。<br />[b]init.py[/b]<br /><br />import sqltrace<br />import sqltrace_hook<br />import res_users<br /><br />[b]openerp.py[/b]<br /><br />{<br />    'name': 'SQL trace',<br />    'version': '1.0',<br />    'author': 'xxx',<br />    'website': '',<br />    'category': 'xxxx',<br />    'sequence': 100,<br />    'summary': 'SQL trace',<br />    'images': [<br />            ],<br />    'depends': [<br />        'mail',<br />    ],<br />    'description': """<br />    SQL Trace<br />    """,<br />    'data': ['res_users_view.xml'<br />    ],<br />    'test': [<br />    ],<br />    'installable': True,<br />    'auto_install': False,<br />    'application': True,<br />}<br /><br />[b]sqltrace_hook.py[/b]<br /><br />from openerp.osv import orm<br />import datetime<br /><br /><br />_search_original = orm.BaseModel._search<br /><br /><br />def _search(self, cr, user, args, offset=0, limit=None, order=None, context=None, count=False, access_rights_uid=None):<br />    start = datetime.datetime.now()<br />    result = _search_original(self, cr, user, args, offset, limit, order, context, count, access_rights_uid)<br />    duration = datetime.datetime.now() - start<br />    if context:  # make sure context is ready<br />        sql_trace = context.get("sql_trace", False)  # default no trace<br />        sql_module = context.get("sql_module", 'Empty')  # in case global context not ready<br />        sql_model = context.get("sql_model", 'Empty')<br />        if sql_module == 'Empty':<br />            check_module = False<br />        elif not sql_module:    # leave module emtpy to trace all modules<br />            check_module = True<br />        else:<br />            check_module = self._module in sql_module<br />        if sql_model == 'Empty':<br />            check_model = False<br />        elif not sql_model:  # leave model empty to trace all models<br />            check_model = True<br />        else:<br />            check_model = self._name in sql_model<br />        if sql_trace and check_module and check_model:<br />            query = self._where_calc(cr, user, args, context=context)<br />            self._apply_ir_rules(cr, user, query, 'read', context=context)<br />            order_by = self._generate_order_by(order, query)<br />            from_clause, where_clause, where_clause_params = query.get_sql()<br />            where_str = where_clause and (" WHERE %s" % where_clause) or ''<br />            limit_str = limit and ' limit %d' % limit or ''<br />            offset_str = offset and ' offset %d' % offset or ''<br />            query_str = 'SELECT "%s".id FROM ' % self._table + from_clause + where_str + order_by + limit_str + offset_str<br />            cr.execute("""INSERT INTO sqltrace (module,model,statement,user_id,sql,parameters, result, duration, date_update)<br />                                VALUES (%s,%s, %s, %s,%s, %s, %s ,%s, (now() at time zone 'UTC'))""",<br />                                (self._module, self._name, 'select', user, query_str, reduce(lambda x, y: str(x)+' ,'+str(y),<br />                                where_clause_params or ['']), str(result or ['']), duration.seconds))<br />    return result<br />orm.BaseModel._search = _search<br /><br />[b]sqltrace.py[/b]<br />from openerp import models, fields, api, _<br /><br /><br />class SQLTrace(models.Model):<br />    """ workstation """<br />    _name = 'sqltrace'<br />    _description = 'SQL Trace'<br /><br />    module = fields.Char()<br />    model = fields.Char()<br />    statement = fields.Char()<br />    user_id = fields.Many2one('res.users')<br />    sql = fields.Text()<br />    parameters = fields.Text()<br />    result = fields.Text()<br />    date_update = fields.Datetime()<br />    duration = fields.Float()<br /><br />[b]res_users.py[/b]<br /><br />from openerp import models, fields, api, _<br /><br />class res_users(models.Model):<br />    _inherit = 'res.users'<br /><br />    context_sql_trace = fields.Boolean('Activate SQL Trace?')<br />    context_sql_module = fields.Char('Modules for SQL Trace')<br />    context_sql_model = fields.Char('Models for SQL Trace')<br /><br />res_users_view.xml<br /><openerp><br />    <data><br />        <record model="ir.ui.view" id="sqltrace_user_view"><br />            <field name="name">sqltrace.user.view.inherit</field><br />            <field name="model">res.users</field><br />            <field name="inherit_id" ref="base.view_users_form"/><br />            <field name="priority" eval="20"/><br />            <field name="arch" type="xml"><br />                <field name="tz" position="after"><br />                    <group string="SQL Trace" name="SQLTrace"><br />                        <field name="context_sql_trace"/><br />                        <field name="context_sql_module"/><br />                        <field name="context_sql_model"/><br />                    </group><br />                </field><br />            </field><br />        </record><br />    </data><br /></openerp><br /><br /><br />重点分享<br />1. 在用户表中增加的栏位以context_开头的话,就会被自动加到全局的context中,有缓存的作用<br />2. 因为_search会在context可用前被调用,所以需要判断context是否可用<br />3. 解析SQL语句内容的部分从原models.py中的_search抄过来的



  • 因为是在users表里增加了栏位,新模块加载未安装前可能会报用户表里的新栏位不存在的错误,这时可以直接在数据库里先手工增加这些栏位就可以了。



  • 谢谢分享,Mark之,<br />另外祝新年进步!身体健康!财源广进!



  • 赞...................!!!!


登录后回复
 

与 Odoo 中文社区 的连接断开,我们正在尝试重连,请耐心等待