diff options
| author | Sébastien Theys <seb@odoo.com> | 2020-02-25 12:45:11 +0000 |
|---|---|---|
| committer | Sébastien Theys <seb@odoo.com> | 2020-02-25 13:46:10 +0000 |
| commit | 6bb0963b6adb588925be9789e9b380eb437a13d2 (patch) | |
| tree | a9a345ffda88f5752fec9e2d8cdce85183c7cc86 /odoo/addons/test_new_api/tests/test_new_fields.py | |
| parent | 93f10cb6291d3855353e36771e06c08d04b4464f (diff) | |
[IMP] core: optimize read() by avoiding useless query
When the `select` returns nothing more than ids that are already known, there is
no need to make it at all.
This removes one query from `_read` every time it has to fetch only fields that
are stored in a different table (o2m, ...), which happens all the time when
reading a stored field first (triggering prefetch) and then reading a o2m.
The query that is now removed was used to check access rules, but the trick is
to use `check_access_rule` to verify the rules in python instead.
Part of task-2061122
closes odoo/odoo#36263
Signed-off-by: Sébastien Theys (seb) <seb@odoo.com>
Diffstat (limited to 'odoo/addons/test_new_api/tests/test_new_fields.py')
| -rw-r--r-- | odoo/addons/test_new_api/tests/test_new_fields.py | 47 |
1 files changed, 47 insertions, 0 deletions
diff --git a/odoo/addons/test_new_api/tests/test_new_fields.py b/odoo/addons/test_new_api/tests/test_new_fields.py index b98b1a34c0f..94b1dd9c04e 100644 --- a/odoo/addons/test_new_api/tests/test_new_fields.py +++ b/odoo/addons/test_new_api/tests/test_new_fields.py @@ -1714,6 +1714,53 @@ class TestFields(TransactionCaseWithUserDemo): self.assertEqual(record_no_bin_size.binary_computed, expected_value) self.assertEqual(record_bin_size.binary_computed, expected_value) + def test_96_ir_rule_m2m_field(self): + """Ensures m2m fields can't be read if the left records can't be read. + Also makes sure reading m2m doesn't take more queries than necessary.""" + tag = self.env['test_new_api.multi.tag'].create({}) + record = self.env['test_new_api.multi.line'].create({ + 'name': 'image', + 'tags': [(4, tag.id)], + }) + + # only one query as admin: reading pivot table + with self.assertQueryCount(1): + record.read(['tags']) + + user = self.env['res.users'].create({'name': "user", 'login': "user"}) + record_user = record.with_user(user) + + # prep the following query count by caching access check related data + record_user.read(['tags']) + + # only one query as user: reading pivot table + with self.assertQueryCount(1): + record_user.read(['tags']) + + # create a passing ir.rule + self.env['ir.rule'].create({ + 'model_id': self.env['ir.model']._get(record._name).id, + 'domain_force': "[('id', '=', %d)]" % record.id, + }) + + # prep the following query count by caching access check related data + record_user.read(['tags']) + + # still only 1 query: reading pivot table + # access rules are checked in python in this case + with self.assertQueryCount(1): + record_user.read(['tags']) + + # create a blocking ir.rule + self.env['ir.rule'].create({ + 'model_id': self.env['ir.model']._get(record._name).id, + 'domain_force': "[('id', '!=', %d)]" % record.id, + }) + + # ensure ir.rule is applied even when reading m2m + with self.assertRaises(AccessError): + record_user.read(['tags']) + class TestX2many(common.TransactionCase): def test_definition_many2many(self): |
