From 8fc4a9830488bd93fb87f826276b766bd1b4e03a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Tue, 22 Apr 2008 17:47:24 +0200 Subject: [PATCH] Use dict for _order on ORM object. _order is now an instanciate variable. It is a dict like this: [('name', 'ASC'), ('id', 'ASC')] --- trytond/ir/action.py | 5 +++- trytond/ir/model.py | 1 - trytond/ir/module/category.py | 5 +++- trytond/ir/module/module.py | 7 +++-- trytond/ir/rule.py | 6 ++++- trytond/ir/translation.py | 7 ++++- trytond/ir/ui/menu.py | 5 +++- trytond/ir/ui/view.py | 4 +-- trytond/osv/fields.py | 5 ++-- trytond/osv/orm.py | 50 +++++++++++++++++++++++++++-------- trytond/res/request.py | 9 +++++-- trytond/tools/convert.py | 4 +-- 12 files changed, 81 insertions(+), 27 deletions(-) diff --git a/trytond/ir/action.py b/trytond/ir/action.py index d30c61ae52..79011ce011 100644 --- a/trytond/ir/action.py +++ b/trytond/ir/action.py @@ -303,7 +303,10 @@ class ActionActWindowView(OSV): multi = fields.Boolean('On multiple doc.', help="If set to true, the action will not be displayed \n" \ "on the right toolbar of a form views.") - _order = 'sequence' + + def __init__(self): + super(ActionActWindowView, self).__init__() + self._order.insert(0, ('sequence', 'ASC')) def default_multi(self, cursor, user, context=None): return False diff --git a/trytond/ir/model.py b/trytond/ir/model.py index 391c9c306e..feca27a07e 100644 --- a/trytond/ir/model.py +++ b/trytond/ir/model.py @@ -37,7 +37,6 @@ class ModelField(OSV): group_name = fields.Char('Group Name', size=128) view_load = fields.Boolean('View Auto-Load') help = fields.Text('Help', translate=True) - _order = "id" def default_relate(self, cursor, user, context=None): return 0 diff --git a/trytond/ir/module/category.py b/trytond/ir/module/category.py index 5deee3d872..ecf66dd2f3 100644 --- a/trytond/ir/module/category.py +++ b/trytond/ir/module/category.py @@ -11,6 +11,9 @@ class Category(OSV): 'Parent Category', select=1) childs = fields.One2Many('ir.module.category', 'parent', 'Parent Category') - _order = 'name' + + def __init__(self): + super(Category, self).__init__() + self._order.insert(0, ('name', 'ASC')) Category() diff --git a/trytond/ir/module/module.py b/trytond/ir/module/module.py index cf7f0daa4b..575b6f2581 100644 --- a/trytond/ir/module/module.py +++ b/trytond/ir/module/module.py @@ -148,7 +148,6 @@ class Module(OSV): license = fields.Selection([('GPL-2', 'GPL-2'), ('Other proprietary', 'Other proprietary')], string='License', readonly=True) - _order = 'name' def __init__(self): super(Module, self).__init__() @@ -156,6 +155,7 @@ class Module(OSV): ('name_uniq', 'unique (name)', 'The name of the module must be unique!'), ] + self._order.insert(0, ('name', 'ASC')) def default_state(self, cursor, user, context=None): return 'uninstalled' @@ -461,7 +461,10 @@ class ModuleConfigWizardItem(OSV): ('open', 'Open'), ('done', 'Done'), ], string='State', required=True) - _order = 'sequence' + + def __init__(self): + super(ModuleConfigWizardItem, self).__init__() + self._order.insert(0, ('sequence', 'ASC')) def default_state(self, cursor, user, context=None): return 'open' diff --git a/trytond/ir/rule.py b/trytond/ir/rule.py index 510dd11fdd..27fbeab8cd 100644 --- a/trytond/ir/rule.py +++ b/trytond/ir/rule.py @@ -20,7 +20,11 @@ class RuleGroup(OSV): 'rule_group_id', 'group_id', 'Groups') users = fields.Many2Many('res.user', 'user_rule_group_rel', 'rule_group_id', 'user_id', 'Users') - _order = 'model, global_p DESC' + + def __init__(self): + super(RuleGroup, self).__init__() + self._order.insert(0, ('model', 'ASC')) + self._order.insert(1, ('global_p', 'DESC')) def default_global_p(self, cursor, user, context=None): return 1 diff --git a/trytond/ir/translation.py b/trytond/ir/translation.py index 25c8e136ea..a788d2561d 100644 --- a/trytond/ir/translation.py +++ b/trytond/ir/translation.py @@ -388,7 +388,12 @@ class Translation(OSV, Cacheable): translation_ids = self.search(cursor, user, [ ('lang', '=', lang), ('module', '=', module), - ], order="type, name, src, res_id", context=context) + ], order=[ + ('type', 'ASC'), + ('name', 'ASC'), + ('src', 'ASC'), + ('res_id', 'ASC'), + ], context=context) for translation in self.browse(cursor, user, translation_ids, context=context): row = [] diff --git a/trytond/ir/ui/menu.py b/trytond/ir/ui/menu.py index e20a316ce3..efb80c1bce 100644 --- a/trytond/ir/ui/menu.py +++ b/trytond/ir/ui/menu.py @@ -124,7 +124,10 @@ class UIMenu(OSV): ('ir.action.wizard', 'ir.action.wizard'), ('ir.action.url', 'ir.action.url'), ]) - _order = "sequence, id" + + def __init__(self): + super(UIMenu, self).__init__() + self._order.insert(0, ('sequence', 'ASC')) def default_icon(self, cursor, user, context=None): return 'STOCK_OPEN' diff --git a/trytond/ir/ui/view.py b/trytond/ir/ui/view.py index 05ec59635f..822354dccc 100644 --- a/trytond/ir/ui/view.py +++ b/trytond/ir/ui/view.py @@ -24,13 +24,13 @@ class View(OSV): inherit = fields.Many2One('ir.ui.view', 'Inherited View') field_childs = fields.Char('Childs Field',size=64) module = fields.Char('Module', size=128, readonly=True) - _order = "priority" def __init__(self): super(View, self).__init__() self._constraints += [ ('check_xml', 'Invalid XML for View Architecture!', ['arch']) ] + self._order.insert(0, ('priority', 'ASC')) def default_arch(self, cursor, user, context=None): return '' @@ -203,11 +203,11 @@ class ViewShortcut(OSV): user_id = fields.Many2One('res.user', 'User Ref.', required=True, ondelete='cascade') resource = fields.Char('Resource Name', size=64, required=True) - _order = 'sequence' def __init__(self): super(ViewShortcut, self).__init__() self._rpc_allowed.append('get_sc') + self._order.insert(0, ('sequence', 'ASC')) def get_sc(self, cursor, user, user_id, model='ir.ui.menu', context=None): "Provide user's shortcuts" diff --git a/trytond/osv/fields.py b/trytond/osv/fields.py index 8ac17410f7..6347ac9ecf 100644 --- a/trytond/osv/fields.py +++ b/trytond/osv/fields.py @@ -494,8 +494,9 @@ class Many2Many(Column): self._rel + '.' + self._id1 + ' IN (' + ids_s + ') ' \ 'AND ' + self._rel + '.' + self._id2 + ' = ' + \ obj._table + '.id ' + domain1 + \ - limit_str + ' ORDER BY ' + obj._table + '.' + \ - (self._order or obj._order) + \ + limit_str + ' ORDER BY ' + \ + ','.join([obj._table + '.' + x[0] + ' ' + x[1] \ + for x in (self._order or obj._order)]) + \ ' OFFSET %s', domain2 + [offset]) for i in cursor.fetchall(): res[i[1]].append(i[0]) diff --git a/trytond/osv/orm.py b/trytond/osv/orm.py index bc7e0c1d11..595808bd1d 100644 --- a/trytond/osv/orm.py +++ b/trytond/osv/orm.py @@ -195,7 +195,7 @@ class ORM(object): _rec_name = 'name' _parent_name = 'parent' _date_name = 'date' - _order = 'id' + _order = None _inherits = {} #XXX remove from class instance _sequence = None _description = '' @@ -730,6 +730,7 @@ class ORM(object): self._sql_constraints = [] self._constraints = [] self._inherit_fields = [] + self._order = [('id', 'ASC')] # reinit the cache on _columns and _defaults self.__columns = None self.__defaults = None @@ -752,6 +753,7 @@ class ORM(object): 'Last modification by', readonly=True) self.write_date = fields.DateTime( 'Last modification date', readonly=True) + self.id = fields.Integer('ID', readonly=True) for name in self._columns: if isinstance(self._columns[name], (fields.Selection, fields.Reference)) \ @@ -1099,7 +1101,9 @@ class ORM(object): ' FROM ' + table_query + '\"' + self._table +'\" ' \ 'WHERE id IN ' \ '(' + ','.join([str(x) for x in sub_ids]) + ')'\ - ' AND ' + domain1 + ' ORDER BY ' + self._order), + ' AND ' + domain1 + ' ORDER BY ' + \ + ','.join([self._table + '.' + x[0] + ' ' + x[1] \ + for x in self._order])), domain2) if not cursor.rowcount == len({}.fromkeys(sub_ids)): raise ExceptORM('AccessError', @@ -1112,7 +1116,9 @@ class ORM(object): ' FROM ' + table_query + '\"' + self._table + '\" ' \ 'WHERE id IN ' \ '(' + ','.join([str(x) for x in sub_ids]) + ')'\ - ' ORDER BY ' + self._order) + ' ORDER BY ' + \ + ','.join([self._table + '.' + x[0] + ' ' + x[1] \ + for x in self._order])) res.extend(cursor.dictfetchall()) else: res = [{'id': x} for x in ids] @@ -1525,7 +1531,6 @@ class ORM(object): user = user id vals = dictionary of the form {'field_name': field_value, ...} """ - if self._table_query: return False @@ -2042,14 +2047,14 @@ class ORM(object): table = self if args[i][0] in self._inherit_fields: - table = self.pool.get(self._inherit_fields[args[i][0]][0]) + itable = self.pool.get(self._inherit_fields[args[i][0]][0]) table_query = '' - if table._table_query: + if itable._table_query: table_query = '(' + self._table_query + ') AS ' - if (table_query + '"' + table._table + '"' not in tables): - tables.append(table_query + '"' + table._table + '"') + if (table_query + '"' + itable._table + '"' not in tables): + tables.append(table_query + '"' + itable._table + '"') joins.append(('id', 'join', '%s.%s' % \ - (self._table, self._inherits[table._name]), table)) + (self._table, self._inherits[itable._name]), itable)) fargs = args[i][0].split('.', 1) field = table._columns.get(fargs[0], False) if not field: @@ -2351,8 +2356,31 @@ class ORM(object): qu1 = ' WHERE ' + ' AND '.join(qu1) else: qu1 = '' - #XXX should be better if order where smthg like [('name','desc'),('name','asc')]: - order_by = order and order.replace(';','\;') or self._order + + order_by = [] + for field, otype in (order or self._order): + if otype.upper() not in ('DESC', 'ASC'): + raise ExceptORM('Error', 'Wrong order type (%s)!' % otype) + if (field not in self._columns \ + or not self._columns[field]._classic_write) \ + and (field not in self._inherit_fields.keys() \ + or not self._inherit_fields[field][2]._classic_write): + raise ExceptORM('Error', 'Wrong field name (%s) in order!' \ + % field) + if field in self._inherit_fields.keys(): + obj = self.pool.get(self._inherit_fields[field][0]) + order_by.append(obj._table + '.' + field + ' ' + otype) + if '"' + obj._table + '"' not in tables: + tables.append('"' + obj._table + '"') + if len(qu1): + qu1 += ' AND ' + else: + qu1 = ' WHERE ' + qu1 += ' %s.%s = %s.id' % (self._table, + self._inherits[obj._name], obj._table) + else: + order_by.append(self._table + '.' + field + ' ' + otype) + order_by = ','.join(order_by) limit_str = limit and (type(limit) in (float, int, long))\ and ' LIMIT %d' % limit or '' diff --git a/trytond/res/request.py b/trytond/res/request.py index 7987351e34..665cb5b46a 100644 --- a/trytond/res/request.py +++ b/trytond/res/request.py @@ -55,7 +55,6 @@ class Request(OSV): ], 'State', required=True, readonly=True) history = fields.One2Many('res.request.history', 'request', 'History', readonly=True) - _order = 'priority DESC, trigger_date, create_date DESC' def default_act_from(self, cursor, user, context=None): return user @@ -77,6 +76,9 @@ class Request(OSV): 'request_close', 'request_get', ] + self._order.insert(0, ('priority', 'DESC')) + self._order.insert(1, ('trigger_date', 'ASC')) + self._order.insert(2, ('create_date', 'DESC')) def links_get(self, cursor, user, context=None): request_link_obj = self.pool.get('res.request.link') @@ -144,7 +146,10 @@ class RequestLink(OSV): name = fields.Char('Name', size=64, required=True, translate=True) object = fields.Char('Object', size=64, required=True) priority = fields.Integer('Priority') - _order = 'priority' + + def __init__(self): + super(RequestLink, self).__init__() + self._order.insert(0, ('priority', 'ASC')) def default_priority(self, cursor, user, context=None): return 5 diff --git a/trytond/tools/convert.py b/trytond/tools/convert.py index 39666647c1..605e908ee1 100644 --- a/trytond/tools/convert.py +++ b/trytond/tools/convert.py @@ -464,7 +464,7 @@ class TrytondXmlHandler(sax.handler.ContentHandler): # problem when the corresponding recordds will be deleted: module_data_ids = self.modeldata_obj.search( self.cursor, self.user, [('module','=',self.module)], - order="id desc", + order=[('id', 'DESC')], ) return [rec.fs_id for rec in self.modeldata_obj.browse( self.cursor, self.user, module_data_ids)] @@ -632,7 +632,7 @@ def post_import(cursor, module, to_delete): mdata_ids = modeldata_obj.search( cursor, user, [('fs_id','in',to_delete)], - order="id desc", + order=[('id', 'DESC')], ) for mrec in modeldata_obj.browse(cursor, user, mdata_ids):