summaryrefslogtreecommitdiff
path: root/odoo/addons/test_new_api/tests/test_new_fields.py
diff options
context:
space:
mode:
authorSébastien Theys <seb@odoo.com>2020-02-25 12:45:11 +0000
committerSébastien Theys <seb@odoo.com>2020-02-25 13:46:10 +0000
commit6bb0963b6adb588925be9789e9b380eb437a13d2 (patch)
treea9a345ffda88f5752fec9e2d8cdce85183c7cc86 /odoo/addons/test_new_api/tests/test_new_fields.py
parent93f10cb6291d3855353e36771e06c08d04b4464f (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.py47
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):