From 37a949e30afc3cb7b604a33c535ace79e62d5490 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Thu, 29 Nov 2012 16:28:52 +0100 Subject: [PATCH] [DOC] First draft of doc on _auto_join, to at least have something. bzr revid: tde@openerp.com-20121129152852-akslcby3ics61vuz --- doc/06_misc.rst | 1 + doc/06_misc_auto_join.rst | 64 ++++++++++++++++++++ openerp/addons/base/tests/test_expression.py | 4 +- 3 files changed, 67 insertions(+), 2 deletions(-) create mode 100644 doc/06_misc_auto_join.rst diff --git a/doc/06_misc.rst b/doc/06_misc.rst index c82022b812e..5a4ae7e008a 100644 --- a/doc/06_misc.rst +++ b/doc/06_misc.rst @@ -10,3 +10,4 @@ Miscellanous 06_misc_need_action_specs.rst 06_misc_user_img_specs.rst 06_misc_import.rst + 06_misc_auto_join.rst diff --git a/doc/06_misc_auto_join.rst b/doc/06_misc_auto_join.rst new file mode 100644 index 00000000000..dab24f1bf09 --- /dev/null +++ b/doc/06_misc_auto_join.rst @@ -0,0 +1,64 @@ +.. _performing_joins_in_select: + +Perfoming joins in select +========================= + +.. versionadded:: 7.0 + +Starting with OpenERP 7.0, an ``_auto_join`` attribute is added on *many2one* and +*one2many* fields. The purpose is to allow the automatic generation of joins in +select queries. This attribute is set to False by default, therefore not changing +the default behavior of those fields. It is not recommended to use this attribute +unless you understand the limitations of the feature. + +Without ``_auto_join``, the behavior of expression.parse() is the same as before. +Leafs holding a path beginning with many2one or one2many fields perform a search +on the relational table. The result is then used to replace the leaf content. +For example, if you have on res.partner a domain like ``[('bank_ids.name', +'like', 'foo')]`` with bank_ids linking to res.partner.bank, 3 queries will be +performed : + +- 1 on res_partner_bank, with domain ``[('name', '=', 'foo')]``, that returns a + list of (res.partner.bank) bids +- 1 on res_partner, with a domain ``['bank_ids', 'in', bids)]``, that returns a + list of (res.partner) pids +- 1 on res_partner, with a domain ``[('id', 'in', pids)]`` + +When the _auto_join attribute is True, it will perform a select on res_partner +as well as on res_partner_bank. + +- the relational table will be accessed through an alias: ``'"res_partner_bank" + as res_partner__bank_ids`` +- the relational table will have a join condition on the main table: + ``res_partner__bank_ids."partner_id"=res_partner."id"`` +- the condition will be written on the relational table: + ``res_partner__bank_ids."name" = 'foo'`` + +This job is performed in expression.parse(). For leafs containing a path, it +checks whether the first item of the path is a *many2one* or *one2many* field +with the ``auto_join`` attribute set. If set, it adds a join query and recursively +analyzes the remaining of the leaf, going back to the normal behavior when +not reaching an ``_auto_join`` field. The sql condition created from the leaf +will be updated to take into account the table aliases. + +Chaining _auto_join allows to reduce the number of queries performed, and to +avoid having too long ``('id', 'in', ids)`` replacement leafs in domains. +However, severe limitations exist on this feature that limits its current use as +of version 7.0. **This feature is therefore considered as experimental, and used +to speedup some precise bottlenecks in OpenERP**. + +List of known issues and limitations: + +- using _auto_join bypasses the business logic; no name search is performed, only + direct matches between ids using join conditions +- ir.rules are not taken into account when performing the _auto_join. +- support of active_test is not asserted +- support of translation is not asserted +- support of _auto_join leading to function fields + +Typical use in OpenERP 7.0: + +- in mail module: notification_ids field on mail_message, allowing to speedup + the display of the various mailboxes +- in mail module: message_ids field on mail_thread, allowing to speedup the + display of needaction counters and documents having unread messages diff --git a/openerp/addons/base/tests/test_expression.py b/openerp/addons/base/tests/test_expression.py index 1eb22ccba43..d3fe9de3efd 100644 --- a/openerp/addons/base/tests/test_expression.py +++ b/openerp/addons/base/tests/test_expression.py @@ -137,7 +137,7 @@ class test_expression(common.TransactionCase): "_auto_join off: ('bank_ids.name', 'like', '..'): incorrect result") # Test produced queries self.assertEqual(len(self.query_list), 3, - "_auto_join off: ('bank_ids.name', 'like', '..') should produce 3 queries (1 in res_partner_bank, 1 on res_partner with active, 1 on res_partner)") + "_auto_join off: ('bank_ids.name', 'like', '..') should produce 3 queries (1 in res_partner_bank, 2 on res_partner)") sql_query = self.query_list[0].get_sql() self.assertIn('res_partner_bank', sql_query[0], "_auto_join off: ('bank_ids.name', 'like', '..') first query incorrect main table") @@ -161,7 +161,7 @@ class test_expression(common.TransactionCase): "_auto_join off: ('child_ids.bank_ids.id', 'in', [..]): incorrect result") # Test produced queries self.assertEqual(len(self.query_list), 5, - "_auto_join off: ('child_ids.bank_ids.id', 'in', [..]) should produce 5 queries (1 in res_partner_bank, 2 on res_partner with active, 2 on res_partner, childs then parents)") + "_auto_join off: ('child_ids.bank_ids.id', 'in', [..]) should produce 5 queries (1 in res_partner_bank, 4 on res_partner)") # Do: one2many with _auto_join partner_bank_ids_col._auto_join = True