[IMP] orm.read(): properly support ir.rules using fields inherited from _inherits + cleanup

bzr revid: odo@openerp.com-20100713131631-w1dvsbcm8a78d5dc
This commit is contained in:
Olivier Dony 2010-07-13 15:16:31 +02:00
parent f61cf6facf
commit 472693f703
1 changed files with 18 additions and 21 deletions

View File

@ -2835,14 +2835,16 @@ class orm(orm_template):
def _read_flat(self, cr, user, ids, fields_to_read, context=None, load='_classic_read'): def _read_flat(self, cr, user, ids, fields_to_read, context=None, load='_classic_read'):
if not context: if not context:
context = {} context = {}
#ids = map(lambda x:int(x), ids)
if not ids: if not ids:
return [] return []
if fields_to_read == None: if fields_to_read == None:
fields_to_read = self._columns.keys() fields_to_read = self._columns.keys()
# construct a clause for the rules : # Construct a clause for the security rules.
d1, d2, tables = self.pool.get('ir.rule').domain_get(cr, user, self._name, 'read', context=context) # 'tables' hold the list of tables necessary for the SELECT including the ir.rule clauses,
# or will at least contain self._table.
rule_clause, rule_params, tables = self.pool.get('ir.rule').domain_get(cr, user, self._name, 'read', context=context)
# all inherited fields + all non inherited fields for which the attribute whose name is in load is True # all inherited fields + all non inherited fields for which the attribute whose name is in load is True
fields_pre = [f for f in fields_to_read if fields_pre = [f for f in fields_to_read if
f == self.CONCURRENCY_CHECK_FIELD f == self.CONCURRENCY_CHECK_FIELD
@ -2852,25 +2854,27 @@ class orm(orm_template):
res = [] res = []
if len(fields_pre): if len(fields_pre):
def convert_field(f): def convert_field(f):
f_qual = "%s.%s" % (self._table, f) # need fully-qualified references in case len(tables) > 1
if f in ('create_date', 'write_date'): if f in ('create_date', 'write_date'):
return "date_trunc('second', %s) as %s" % (f, f) return "date_trunc('second', %s) as %s" % (f_qual, f)
if f == self.CONCURRENCY_CHECK_FIELD: if f == self.CONCURRENCY_CHECK_FIELD:
if self._log_access: if self._log_access:
return "COALESCE(%s.write_date, %s.create_date, now())::timestamp AS %s" % (self._table, self._table, f,) return "COALESCE(%s.write_date, %s.create_date, now())::timestamp AS %s" % (self._table, self._table, f,)
return "now()::timestamp AS %s" % (f,) return "now()::timestamp AS %s" % (f,)
if isinstance(self._columns[f], fields.binary) and context.get('bin_size', False): if isinstance(self._columns[f], fields.binary) and context.get('bin_size', False):
return 'length("%s") as "%s"' % (f, f) return 'length("%s") as "%s"' % (f_qual, f)
return '"%s"' % (f,) return f_qual
fields_pre2 = map(convert_field, fields_pre) fields_pre2 = map(convert_field, fields_pre)
order_by = self._parent_order or self._order order_by = self._parent_order or self._order
select_fields = ','.join(fields_pre2 + ['id']) select_fields = ','.join(fields_pre2 + [self._table + '.id'])
query = 'SELECT %s FROM "%s" WHERE id IN %%s' % (select_fields, self._table) query = 'SELECT %s FROM %s WHERE %s.id IN %%s' % (select_fields, ','.join(tables), self._table)
if d1: if rule_clause:
query += " AND " + (' OR '.join(d1)) query += " AND " + (' OR '.join(rule_clause))
query += " ORDER BY " + order_by query += " ORDER BY " + order_by
for sub_ids in cr.split_for_in_conditions(ids): for sub_ids in cr.split_for_in_conditions(ids):
if d1: if rule_clause:
cr.execute(query, [tuple(sub_ids)] + d2) cr.execute(query, [tuple(sub_ids)] + rule_params)
if cr.rowcount != len(sub_ids): if cr.rowcount != len(sub_ids):
raise except_orm(_('AccessError'), raise except_orm(_('AccessError'),
_('You try to bypass an access rule while reading (Document type: %s).') % self._description) _('You try to bypass an access rule while reading (Document type: %s).') % self._description)
@ -2884,7 +2888,7 @@ class orm(orm_template):
if f == self.CONCURRENCY_CHECK_FIELD: if f == self.CONCURRENCY_CHECK_FIELD:
continue continue
if self._columns[f].translate: if self._columns[f].translate:
ids = map(lambda x: x['id'], res) ids = [x['id'] for x in res]
#TODO: optimize out of this loop #TODO: optimize out of this loop
res_trans = self.pool.get('ir.translation')._get_ids(cr, user, self._name+','+f, 'model', context.get('lang', False) or 'en_US', ids) res_trans = self.pool.get('ir.translation')._get_ids(cr, user, self._name+','+f, 'model', context.get('lang', False) or 'en_US', ids)
for r in res: for r in res:
@ -2915,7 +2919,7 @@ class orm(orm_template):
for r in res: for r in res:
for f in fields_post: for f in fields_post:
r[f] = self._columns[f]._symbol_get(r[f]) r[f] = self._columns[f]._symbol_get(r[f])
ids = map(lambda x: x['id'], res) ids = [x['id'] for x in res]
# all non inherited fields for which the attribute whose name is in load is False # 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_to_read) fields_post = filter(lambda x: x in self._columns and not getattr(self._columns[x], load), fields_to_read)
@ -2940,13 +2944,6 @@ class orm(orm_template):
record[f] = res2[record['id']] record[f] = res2[record['id']]
else: else:
record[f] = [] record[f] = []
#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 readonly = None
for vals in res: for vals in res:
for field in vals.copy(): for field in vals.copy():