Merge lp:~openerp-dev/openobject-server/6.0-opw-577963-xal into lp:openobject-server/6.0

Proposed by Xavier ALT
Status: Merged
Approved by: Xavier ALT
Approved revision: 3633
Merged at revision: 3633
Proposed branch: lp:~openerp-dev/openobject-server/6.0-opw-577963-xal
Merge into: lp:openobject-server/6.0
Diff against target: 37 lines (+13/-4)
1 file modified
bin/addons/base/ir/ir_attachment.py (+13/-4)
To merge this branch: bzr merge lp:~openerp-dev/openobject-server/6.0-opw-577963-xal
Reviewer Review Type Date Requested Status
OpenERP Core Team Pending
Review via email: mp+120587@code.launchpad.net

Description of the change

Hi,

This improve the speed of ir.attachment search() method - making this usable for database with 100k+ attachments.
(coutesy of Mr. Olivier Dony)

Regards,
Xavier

To post a comment you must log in.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'bin/addons/base/ir/ir_attachment.py'
2--- bin/addons/base/ir/ir_attachment.py 2011-05-02 11:57:10 +0000
3+++ bin/addons/base/ir/ir_attachment.py 2012-08-21 14:47:51 +0000
4@@ -65,10 +65,18 @@
5 return 0
6 return []
7
8+ # Work with a set, as list.remove() is prohibitive for large lists of documents
9+ # (takes 20+ seconds on a db with 100k docs during search_count()!)
10+ orig_ids = ids
11+ ids = set(ids)
12+
13 # For attachments, the permissions of the document they are attached to
14 # apply, so we must remove attachments for which the user cannot access
15 # the linked document.
16- targets = super(ir_attachment,self).read(cr, uid, ids, ['id', 'res_model', 'res_id'])
17+ # Use pure SQL rather than read() as it is about 50% faster for large dbs (100k+ docs),
18+ # and the permissions are checked in super() and below anyway.
19+ cr.execute("""SELECT id, res_model, res_id FROM ir_attachment WHERE id = ANY(%s)""", (list(ids),))
20+ targets = cr.dictfetchall()
21 model_attachments = {}
22 for target_dict in targets:
23 if not (target_dict['res_id'] and target_dict['res_model']):
24@@ -93,9 +101,10 @@
25 for res_id in disallowed_ids:
26 for attach_id in targets[res_id]:
27 ids.remove(attach_id)
28- if count:
29- return len(ids)
30- return ids
31+
32+ # sort result according to the original sort ordering
33+ result = [id for id in orig_ids if id in ids]
34+ return len(result) if count else list(result)
35
36 def read(self, cr, uid, ids, fields_to_read=None, context=None, load='_classic_read'):
37 self.check(cr, uid, ids, 'read', context=context)