Apply the function field searcher transformation before doing any optimization

This allows to use the OR-to-UNION optimization if the searcher returns only
local columns.
This commit is contained in:
Nicolas Évrard
2024-06-27 19:15:07 +02:00
parent 02f054bd26
commit 1fbcf70283
3 changed files with 44 additions and 0 deletions
+16
View File
@@ -22,6 +22,7 @@ from trytond.pool import Pool
from trytond.pyson import PYSONDecoder, PYSONEncoder
from trytond.rpc import RPC
from trytond.tools import cursor_dict, grouped_slice, reduce_ids
from trytond.tools.domain_inversion import simplify
from trytond.transaction import (
Transaction, inactive_records, record_cache_size, without_check_access)
@@ -1691,6 +1692,21 @@ class ModelSQL(ModelStorage):
pool = Pool()
Rule = pool.get('ir.rule')
def convert(domain):
if is_leaf(domain):
fname, *_ = domain[0].split('.', 1)
field = cls._fields[fname]
if isinstance(field, fields.Function) and field.searcher:
new_leaf = getattr(cls, field.searcher)(fname, domain)
return new_leaf
else:
return domain
elif isinstance(domain, str):
return domain
else:
return [convert(d) for d in domain]
domain = simplify(convert(domain))
rule_domain = Rule.domain_get(cls.__name__, mode='read')
joined_domains = None
if domain and domain[0] == 'OR':
+7
View File
@@ -152,6 +152,13 @@ class ModelSQLSearchOR2Union(ModelSQL):
}
return [table.integer + target.id]
@classmethod
def search_rec_name(cls, name, clause):
return ['OR',
('name',) + clause[1:],
('targets.name',) + clause[1:],
]
class ModelSQLSearchOR2UnionTarget(ModelSQL):
"ModelSQL Target to test read"
+21
View File
@@ -1251,6 +1251,27 @@ class ModelSQLTestCase(TestCase):
self.assertEqual(Model.search(domain), [model_c, model_a])
self.assertIn('UNION', str(Model.search(domain, query=True)))
@with_transaction()
def test_search_or_to_union_function_field(self):
pool = Pool()
Model = pool.get('test.modelsql.search.or2union')
model_a, model_b, model_c = Model.create([{
'name': 'A',
}, {
'name': 'B',
}, {
'name': 'C',
'targets': [
('create', [{'name': 'A'}]),
],
},
])
domain = [('rec_name', '=', 'A')]
self.assertEqual(Model.search(domain), [model_a, model_c])
self.assertIn('UNION', str(Model.search(domain, query=True)))
@with_transaction()
def test_search_limit(self):
"Test searching with limit"