changeset 3b5056ac4f06 in trytond:default
details: https://hg.tryton.org/trytond?cmd=changeset&node=3b5056ac4f06
description:
Add limit to search count
issue10967
review389301002
diffstat:
CHANGELOG | 1 +
doc/ref/models/models.rst | 4 +++-
trytond/model/modelsql.py | 14 +++++++++++---
trytond/model/modelstorage.py | 5 +++--
trytond/tests/test_modelsql.py | 24 ++++++++++++++++++++++++
5 files changed, 42 insertions(+), 6 deletions(-)
diffs (101 lines):
diff -r f6a2a8cc9081 -r 3b5056ac4f06 CHANGELOG
--- a/CHANGELOG Sun Jan 23 22:06:21 2022 +0100
+++ b/CHANGELOG Sun Jan 30 01:42:23 2022 +0100
@@ -1,3 +1,4 @@
+* Support limit and offset to ModelSQL count search and search_count
* Apply view inheritance to board
* Add RPC view_get method to View
* Apply view inheritance to all matching elements
diff -r f6a2a8cc9081 -r 3b5056ac4f06 doc/ref/models/models.rst
--- a/doc/ref/models/models.rst Sun Jan 23 22:06:21 2022 +0100
+++ b/doc/ref/models/models.rst Sun Jan 30 01:42:23 2022 +0100
@@ -340,10 +340,12 @@
sort on the key's value.
If ``count`` is set to ``True``, then the result is the number of records.
+ The count result is limited upto the value of ``limit`` if set.
-.. classmethod:: ModelStorage.search_count(domain)
+.. classmethod:: ModelStorage.search_count(domain[, offset[, limit]])
Return the number of records that match the :ref:`domain <topics-domain>`.
+ The result is limited upto the value of ``limit`` if set and reduced by
offset.
.. classmethod:: ModelStorage.search_read(domain[, offset[, limit[, order[,
fields_names]]]])
diff -r f6a2a8cc9081 -r 3b5056ac4f06 trytond/model/modelsql.py
--- a/trytond/model/modelsql.py Sun Jan 23 22:06:21 2022 +0100
+++ b/trytond/model/modelsql.py Sun Jan 30 01:42:23 2022 +0100
@@ -1451,9 +1451,17 @@
main_table, _ = tables[None]
if count:
table = convert_from(None, tables)
- cursor.execute(*table.select(Count(Literal('*')),
- where=expression, limit=limit, offset=offset))
- return cursor.fetchone()[0]
+ if (limit is not None and limit < cls.count()) or offset:
+ select = table.select(
+ Literal(1), where=expression, limit=limit, offset=offset
+ ).select(Count(Literal('*')))
+ else:
+ select = table.select(Count(Literal('*')), where=expression)
+ if query:
+ return select
+ else:
+ cursor.execute(*select)
+ return cursor.fetchone()[0]
order_by = cls.__search_order(order, tables)
# compute it here because __search_order might modify tables
diff -r f6a2a8cc9081 -r 3b5056ac4f06 trytond/model/modelstorage.py
--- a/trytond/model/modelstorage.py Sun Jan 23 22:06:21 2022 +0100
+++ b/trytond/model/modelstorage.py Sun Jan 30 01:42:23 2022 +0100
@@ -543,11 +543,12 @@
return []
@classmethod
- def search_count(cls, domain):
+ def search_count(cls, domain, offset=0, limit=None):
'''
Return the number of records that match the domain.
'''
- res = cls.search(domain, order=[], count=True)
+ res = cls.search(
+ domain, order=[], count=True, offset=offset, limit=limit)
if isinstance(res, list):
return len(res)
return res
diff -r f6a2a8cc9081 -r 3b5056ac4f06 trytond/tests/test_modelsql.py
--- a/trytond/tests/test_modelsql.py Sun Jan 23 22:06:21 2022 +0100
+++ b/trytond/tests/test_modelsql.py Sun Jan 30 01:42:23 2022 +0100
@@ -916,6 +916,30 @@
self.assertEqual(Model.search(domain), [model_c, model_a])
self.assertIn('UNION', str(Model.search(domain, query=True)))
+ @with_transaction()
+ def test_search_limit(self):
+ "Test searching with limit"
+ pool = Pool()
+ Model = pool.get('test.modelsql.search')
+
+ Model.create([{'name': str(i)} for i in range(10)])
+
+ self.assertEqual(Model.search([], limit=5, count=True), 5)
+ self.assertEqual(Model.search([], limit=20, count=True), 10)
+ self.assertEqual(Model.search([], limit=None, count=True), 10)
+
+ @with_transaction()
+ def test_search_offset(self):
+ "Test searching with offset"
+ pool = Pool()
+ Model = pool.get('test.modelsql.search')
+
+ Model.create([{'name': str(i)} for i in range(10)])
+
+ self.assertEqual(Model.search([], offset=0, count=True), 10)
+ self.assertEqual(Model.search([], offset=5, count=True), 5)
+ self.assertEqual(Model.search([], offset=20, count=True), 0)
+
def test_split_subquery_domain_empty(self):
"""
Test the split of domains in local and relation parts (empty domain)