Remove target_search on Many2One
This commit is contained in:
1 parent
3632c51c18
commit
4f5c0ae3fa
6 files changed
+31
-30
No files matched your search
@@ -1,3 +1,4 @@
|
||||
* Replace target_search by use of count()
|
||||
* Manage domain on id in single value list as unique
|
||||
* Do not validate domain for empty fields
|
||||
* Warn about implicit save() of unsaved relation
|
||||
|
||||
@@ -694,7 +694,7 @@ Instance methods:
|
||||
Many2One
|
||||
--------
|
||||
|
||||
.. class:: Many2One(model_name, string[, left[, right[, path[, ondelete[, datetime_field[, target_search[, search_order[, search_context[, \**options]]]]]]]]])
|
||||
.. class:: Many2One(model_name, string[, left[, right[, path[, ondelete[, datetime_field[, search_order[, search_context[, \**options]]]]]]]])
|
||||
|
||||
A many-to-one relation field that refers to a record of the named model.
|
||||
|
||||
@@ -769,23 +769,6 @@ Many2One
|
||||
:attr:`~trytond.model.ModelSQL._history` to request a value for a given date
|
||||
and time on a historicized model.
|
||||
|
||||
.. attribute:: Many2One.target_search
|
||||
|
||||
Define the kind of SQL query to use when searching on related target.
|
||||
|
||||
Allowed values are:
|
||||
|
||||
- ``subquery``: uses a subquery based on the ids.
|
||||
|
||||
- ``join``: adds a join on the main query.
|
||||
|
||||
``join`` is the default value.
|
||||
|
||||
.. note::
|
||||
|
||||
``join`` could improve the performance if the target has a huge amount of
|
||||
records.
|
||||
|
||||
.. attribute:: Many2One.search_order
|
||||
|
||||
A :ref:`PYSON <ref-pyson>` expression defining the default order used to
|
||||
|
||||
@@ -180,6 +180,13 @@ The number of retries when a database operational error occurs during a request.
|
||||
|
||||
Default: ``5``
|
||||
|
||||
subquery_threshold
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The number of records in the target relation under which a sub-query is used.
|
||||
|
||||
Default: ``1000``
|
||||
|
||||
language
|
||||
~~~~~~~~
|
||||
|
||||
|
||||
@@ -64,6 +64,7 @@ class TrytonConfigParser(configparser.ConfigParser):
|
||||
self.set('database', 'retry', '5')
|
||||
self.set('database', 'language', 'en')
|
||||
self.set('database', 'timeout', str(30 * 60))
|
||||
self.set('database', 'subquery_threshold', str(1_000))
|
||||
self.add_section('request')
|
||||
self.set('request', 'max_size', str(2 * 1024 * 1024))
|
||||
self.set('request', 'max_size_authenticated',
|
||||
|
||||
@@ -5,6 +5,7 @@ from sql.aggregate import Max
|
||||
from sql.conditionals import Coalesce
|
||||
from sql.operators import Or
|
||||
|
||||
from trytond.config import config
|
||||
from trytond.pool import Pool
|
||||
from trytond.pyson import PYSONEncoder
|
||||
from trytond.tools import cached_property, reduce_ids
|
||||
@@ -14,6 +15,8 @@ from .field import (
|
||||
Field, context_validate, instantiate_context, search_order_validate,
|
||||
with_inactive_records)
|
||||
|
||||
_subquery_threshold = config.getint('database', 'subquery_threshold')
|
||||
|
||||
|
||||
class Many2One(Field):
|
||||
'''
|
||||
@@ -23,7 +26,7 @@ class Many2One(Field):
|
||||
_sql_type = 'INTEGER'
|
||||
|
||||
def __init__(self, model_name, string='', left=None, right=None, path=None,
|
||||
ondelete='SET NULL', datetime_field=None, target_search='join',
|
||||
ondelete='SET NULL', datetime_field=None,
|
||||
search_order=None, search_context=None, help='', required=False,
|
||||
readonly=False, domain=None, states=None,
|
||||
on_change=None, on_change_with=None, depends=None, context=None,
|
||||
@@ -57,8 +60,6 @@ class Many2One(Field):
|
||||
self.right = right
|
||||
self.path = path
|
||||
self.datetime_field = datetime_field
|
||||
assert target_search in ['subquery', 'join']
|
||||
self.target_search = target_search
|
||||
self.__search_order = None
|
||||
self.search_order = search_order
|
||||
self.__search_context = None
|
||||
@@ -258,7 +259,7 @@ class Many2One(Field):
|
||||
else:
|
||||
_, target_name = name.split('.', 1)
|
||||
target_domain = [(target_name,) + tuple(domain[1:])]
|
||||
if self.target_search == 'subquery':
|
||||
if Target.count() < _subquery_threshold:
|
||||
query = Target.search(target_domain, order=[], query=True)
|
||||
return column.in_(query)
|
||||
else:
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
# this repository contains the full copyright notices and license terms.
|
||||
import unittest
|
||||
|
||||
from sql import Join
|
||||
|
||||
from trytond.model.exceptions import DomainValidationError
|
||||
from trytond.pool import Pool
|
||||
from trytond.tests.test_tryton import activate_module, with_transaction
|
||||
@@ -157,7 +159,9 @@ class FieldMany2OneTestCase(unittest.TestCase):
|
||||
self.assertListEqual(result, [record])
|
||||
|
||||
@with_transaction()
|
||||
def _test_search_join(self, target_search):
|
||||
def _test_search_join(self, subquery_threshold=1_000):
|
||||
from trytond.model.fields import many2one
|
||||
|
||||
pool = Pool()
|
||||
Target = pool.get('test.many2one_target')
|
||||
Many2One = pool.get('test.many2one')
|
||||
@@ -170,24 +174,28 @@ class FieldMany2OneTestCase(unittest.TestCase):
|
||||
{'many2one': target2},
|
||||
])
|
||||
|
||||
def set_target_search(target_search):
|
||||
Many2One.many2one.target_search = target_search
|
||||
self.addCleanup(set_target_search, Many2One.many2one.target_search)
|
||||
set_target_search(target_search)
|
||||
previous = many2one._subquery_threshold
|
||||
many2one._subquery_threshold = subquery_threshold
|
||||
self.addCleanup(setattr, many2one, '_subquery_threshold', previous)
|
||||
|
||||
many2ones = Many2One.search([
|
||||
('many2one.value', '=', 1),
|
||||
])
|
||||
|
||||
self.assertListEqual(many2ones, [many2one1])
|
||||
|
||||
return Many2One.search([
|
||||
('many2one.value', '=', 1),
|
||||
], query=True)
|
||||
|
||||
def test_search_join(self):
|
||||
"Test search by many2one join"
|
||||
self._test_search_join('join')
|
||||
query = self._test_search_join(0)
|
||||
self.assertIsInstance(query.from_[0], Join)
|
||||
|
||||
def test_search_subquery(self):
|
||||
"Test search by many2one subquery"
|
||||
self._test_search_join('subquery')
|
||||
query = self._test_search_join()
|
||||
self.assertNotIsInstance(query.from_[0], Join)
|
||||
|
||||
@with_transaction()
|
||||
def test_context_attribute(self):
|
||||
|
||||
Reference in new issue
Block a user