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)

Reply via email to