[IMP] core: fetch display_name during name_search
The `name_search` makes at least 2 SQL requests, one to find the records and one to read fields needed to compute the `display_name`. With the default `_compute_display_name`, it only needs to fetch the `_rec_name` field (if there is one), but the ORM perfetch field mechanism will also fetch every prefetchable field (see `_fetch_field`). Then, to avoid running two queries and fetching too many fields, we add the dependency fields (with `_determine_fields_to_fetch`) to the select clause of the `Query` returned by `_name_search`. Part-of: odoo/odoo#122085
This commit is contained in:
@@ -1228,12 +1228,8 @@ class TestQueries(TransactionCase):
|
||||
# search on both 'name' and 'model'
|
||||
self.assertEqual(Model._rec_names_search, ['name', 'model'])
|
||||
|
||||
# warmup
|
||||
Model.name_search('foo')
|
||||
|
||||
Model.name_search('partner')
|
||||
with self.assertQueries(['''
|
||||
SELECT "ir_model"."id"
|
||||
SELECT "ir_model"."id", "ir_model"."name"->>'en_US'
|
||||
FROM "ir_model"
|
||||
WHERE (
|
||||
("ir_model"."name"->>'en_US' ILIKE %s)
|
||||
@@ -1244,9 +1240,8 @@ class TestQueries(TransactionCase):
|
||||
''']):
|
||||
Model.name_search('foo')
|
||||
|
||||
Model.name_search('partner', operator='not ilike')
|
||||
with self.assertQueries(['''
|
||||
SELECT "ir_model"."id"
|
||||
SELECT "ir_model"."id", "ir_model"."name"->>'en_US'
|
||||
FROM "ir_model"
|
||||
WHERE (
|
||||
("ir_model"."name" is NULL OR "ir_model"."name"->>'en_US' not ilike %s)
|
||||
|
||||
@@ -216,6 +216,17 @@ class TestPerformance(SavepointCaseWithUserDemo):
|
||||
expected,
|
||||
)
|
||||
|
||||
@warmup
|
||||
def test_name_search(self):
|
||||
""" Test that `name` is fetch in the same query than the search
|
||||
to compute `display_name` without any additional query """
|
||||
Model = self.env['test_performance.base']
|
||||
record = Model.create({'name': 'blablu'})
|
||||
record.invalidate_recordset()
|
||||
|
||||
with self.assertQueryCount(1):
|
||||
Model.name_search('blablu')
|
||||
|
||||
@users('__system__', 'demo')
|
||||
@warmup
|
||||
def test_write_base(self):
|
||||
|
||||
+9
-1
@@ -1685,7 +1685,15 @@ class BaseModel(metaclass=MetaModel):
|
||||
:return: list of pairs ``(id, text_repr)`` for all matching records.
|
||||
"""
|
||||
ids = self._name_search(name, args, operator, limit=limit, order=self._order)
|
||||
return [(record.id, record.display_name) for record in self.browse(ids).sudo()]
|
||||
|
||||
if isinstance(ids, Query):
|
||||
records = self._fetch_query(ids, self._determine_fields_to_fetch(['display_name']))
|
||||
else:
|
||||
# Some override of `_name_search` return list of ids.
|
||||
records = self.browse(ids)
|
||||
records.fetch(['display_name'])
|
||||
|
||||
return [(record.id, record.display_name) for record in records.sudo()]
|
||||
|
||||
@api.model
|
||||
def _name_search(self, name, domain=None, operator='ilike', limit=None, order=None):
|
||||
|
||||
Reference in New Issue
Block a user