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:
@@ -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':
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
Reference in New Issue
Block a user