details:   https://code.tryton.org/tryton/commit/ce972acc1cf2
branch:    default
user:      Cédric Krier <[email protected]>
date:      Thu Dec 25 09:47:23 2025 +0100
description:
        Do not use Literal to count in SQL

        The * is not actually a parameter of the aggregate function so it is 
better to
        let python-sql manage it with its default value.
diffstat:

 modules/account/account.py                                     |   6 ++--
 modules/account/pyproject.toml                                 |   2 +-
 modules/account_es/pyproject.toml                              |   2 +-
 modules/account_es/reporting_tax.py                            |   4 +-
 modules/marketing_automation/marketing_automation.py           |  12 +++-----
 modules/marketing_automation/marketing_automation_reporting.py |  13 +++------
 modules/marketing_automation/pyproject.toml                    |   1 +
 modules/marketing_email/marketing.py                           |   3 +-
 modules/purchase/product.py                                    |   3 +-
 modules/purchase/purchase.py                                   |   4 +-
 modules/purchase/pyproject.toml                                |   2 +-
 modules/sale_opportunity/opportunity_reporting.py              |   2 +-
 modules/sale_opportunity/pyproject.toml                        |   2 +-
 trytond/trytond/backend/postgresql/database.py                 |   2 +-
 trytond/trytond/backend/sqlite/database.py                     |   2 +-
 trytond/trytond/ir/trigger.py                                  |   2 +-
 trytond/trytond/model/modelsql.py                              |   4 +-
 trytond/trytond/res/notification.py                            |   2 +-
 trytond/trytond/res/user.py                                    |   4 +-
 19 files changed, 33 insertions(+), 39 deletions(-)

diffs (326 lines):

diff -r bb52a833e823 -r ce972acc1cf2 modules/account/account.py
--- a/modules/account/account.py        Tue Nov 25 13:27:24 2025 +0100
+++ b/modules/account/account.py        Thu Dec 25 09:47:23 2025 +0100
@@ -1085,7 +1085,7 @@
             types = [None]
             for name in names:
                 if name == 'line_count':
-                    columns.append(Count(Literal('*')))
+                    columns.append(Count())
                     types.append(None)
                 else:
                     columns.append(
@@ -1593,7 +1593,7 @@
         types = [None, None]
         for name in names:
             if name == 'line_count':
-                columns.append(Count(Literal('*')).as_(name))
+                columns.append(Count().as_(name))
                 types.append(None)
             else:
                 columns.append(Sum(Coalesce(Column(line, name), 0)).as_(name))
@@ -1721,7 +1721,7 @@
                 .join(period, condition=move.period == period.id)
                 .select(
                     move_line.account, period.fiscalyear,
-                    Count(Literal('*')).as_('line_count'),
+                    Count().as_('line_count'),
                     group_by=[move_line.account, period.fiscalyear]))
             cursor.execute(*deferral.update(
                     [deferral.line_count], [counting_query.line_count],
diff -r bb52a833e823 -r ce972acc1cf2 modules/account/pyproject.toml
--- a/modules/account/pyproject.toml    Tue Nov 25 13:27:24 2025 +0100
+++ b/modules/account/pyproject.toml    Thu Dec 25 09:47:23 2025 +0100
@@ -53,7 +53,7 @@
 [tool.hatch.metadata.hooks.tryton]
 dependencies = [
     'python-dateutil',
-    'python-sql >= 0.7',
+    'python-sql >= 1.4',
     'simpleeval',
     ]
 copyright = 'COPYRIGHT'
diff -r bb52a833e823 -r ce972acc1cf2 modules/account_es/pyproject.toml
--- a/modules/account_es/pyproject.toml Tue Nov 25 13:27:24 2025 +0100
+++ b/modules/account_es/pyproject.toml Thu Dec 25 09:47:23 2025 +0100
@@ -55,7 +55,7 @@
 
 [tool.hatch.metadata.hooks.tryton]
 dependencies = [
-    'python-sql >= 1.1.0',
+    'python-sql >= 1.4',
     ]
 copyright = 'COPYRIGHT'
 readme = 'README.rst'
diff -r bb52a833e823 -r ce972acc1cf2 modules/account_es/reporting_tax.py
--- a/modules/account_es/reporting_tax.py       Tue Nov 25 13:27:24 2025 +0100
+++ b/modules/account_es/reporting_tax.py       Thu Dec 25 09:47:23 2025 +0100
@@ -196,8 +196,8 @@
 
             from_ = convert_from(None, tables)
             cursor.execute(*from_.select(
-                    expression, where=where, group_by=(expression,)).select(
-                        Count(Literal('*'))))
+                    expression, where=where, group_by=(expression,))
+                .select(Count()))
             row = cursor.fetchone()
             if row:
                 parties[tax_code.code] += row[0]
diff -r bb52a833e823 -r ce972acc1cf2 
modules/marketing_automation/marketing_automation.py
--- a/modules/marketing_automation/marketing_automation.py      Tue Nov 25 
13:27:24 2025 +0100
+++ b/modules/marketing_automation/marketing_automation.py      Thu Dec 25 
09:47:23 2025 +0100
@@ -15,7 +15,6 @@
 from genshi.template import MarkupTemplate
 from genshi.template import TemplateError as GenshiTemplateError
 from genshi.template import TextTemplate
-from sql import Literal
 from sql.aggregate import Count
 
 import trytond.config as config
@@ -182,8 +181,8 @@
         for sub in grouped_slice(others):
             cursor.execute(*record.select(
                     record.scenario,
-                    Count(Literal('*')),
-                    Count(Literal('*'), filter_=record.blocked),
+                    Count(),
+                    Count(filter_=record.blocked),
                     where=reduce_ids(record.scenario, sub),
                     group_by=record.scenario))
             for id_, all_, blocked in cursor:
@@ -525,10 +524,9 @@
         for sub in grouped_slice(activities):
             cursor.execute(*record_activity.select(
                     record_activity.activity,
-                    Count(Literal('*'),
-                        filter_=record_activity.state == 'done'),
-                    Count(Literal('*'), filter_=record_activity.email_opened),
-                    Count(Literal('*'), filter_=record_activity.email_clicked),
+                    Count(filter_=record_activity.state == 'done'),
+                    Count(filter_=record_activity.email_opened),
+                    Count(filter_=record_activity.email_clicked),
                     where=reduce_ids(record_activity.activity, sub),
                     group_by=record_activity.activity))
             for id_, all_, email_opened, email_clicked in cursor:
diff -r bb52a833e823 -r ce972acc1cf2 
modules/marketing_automation/marketing_automation_reporting.py
--- a/modules/marketing_automation/marketing_automation_reporting.py    Tue Nov 
25 13:27:24 2025 +0100
+++ b/modules/marketing_automation/marketing_automation_reporting.py    Thu Dec 
25 09:47:23 2025 +0100
@@ -99,8 +99,8 @@
     def _columns(cls, tables, withs):
         record = tables['record']
 
-        record_count = Count(Literal('*'))
-        record_count_blocked = Count(Literal('*'), filter_=record.blocked)
+        record_count = Count()
+        record_count_blocked = Count(filter_=record.blocked)
 
         return super()._columns(tables, withs) + [
             record.scenario.as_('scenario'),
@@ -203,12 +203,9 @@
     def _columns(cls, tables, withs):
         record_activity = tables['record_activity']
 
-        record_count = Count(
-            Literal('*'), filter_=record_activity.state == 'done')
-        email_opened = Count(
-            Literal('*'), filter_=record_activity.email_opened)
-        email_clicked = Count(
-            Literal('*'), filter_=record_activity.email_clicked)
+        record_count = Count(filter_=record_activity.state == 'done')
+        email_opened = Count(filter_=record_activity.email_opened)
+        email_clicked = Count(filter_=record_activity.email_clicked)
 
         return super()._columns(tables, withs) + [
             record_activity.activity.as_('activity'),
diff -r bb52a833e823 -r ce972acc1cf2 modules/marketing_automation/pyproject.toml
--- a/modules/marketing_automation/pyproject.toml       Tue Nov 25 13:27:24 
2025 +0100
+++ b/modules/marketing_automation/pyproject.toml       Thu Dec 25 09:47:23 
2025 +0100
@@ -57,6 +57,7 @@
 dependencies = [
     'Genshi',
     'python-dateutil',
+    'python-sql >= 1.4',
     ]
 copyright = 'COPYRIGHT'
 readme = 'README.rst'
diff -r bb52a833e823 -r ce972acc1cf2 modules/marketing_email/marketing.py
--- a/modules/marketing_email/marketing.py      Tue Nov 25 13:27:24 2025 +0100
+++ b/modules/marketing_email/marketing.py      Thu Dec 25 09:47:23 2025 +0100
@@ -11,7 +11,6 @@
 from genshi.core import END, START, Attrs, QName
 from genshi.template import MarkupTemplate
 from genshi.template import TemplateError as GenshiTemplateError
-from sql import Literal
 from sql.aggregate import Count
 
 import trytond.config as config
@@ -257,7 +256,7 @@
 
         subscribed = defaultdict(int)
         query = email.select(
-            email.list_, Count(Literal('*')), group_by=[email.list_])
+            email.list_, Count(), group_by=[email.list_])
         for sub_lists in grouped_slice(lists):
             query.where = (
                 reduce_ids(email.list_, sub_lists)
diff -r bb52a833e823 -r ce972acc1cf2 modules/purchase/product.py
--- a/modules/purchase/product.py       Tue Nov 25 13:27:24 2025 +0100
+++ b/modules/purchase/product.py       Thu Dec 25 09:47:23 2025 +0100
@@ -3,7 +3,6 @@
 import datetime
 from collections import defaultdict
 
-from sql import Literal
 from sql.aggregate import Count, Max
 
 from trytond.i18n import gettext
@@ -407,7 +406,7 @@
             cursor.execute(*table.select(table.currency,
                     where=table.party == self.party.id,
                     group_by=table.currency,
-                    order_by=Count(Literal(1)).desc))
+                    order_by=Count().desc))
             row = cursor.fetchone()
             if row:
                 self.currency, = row
diff -r bb52a833e823 -r ce972acc1cf2 modules/purchase/purchase.py
--- a/modules/purchase/purchase.py      Tue Nov 25 13:27:24 2025 +0100
+++ b/modules/purchase/purchase.py      Thu Dec 25 09:47:23 2025 +0100
@@ -6,7 +6,7 @@
 from decimal import Decimal
 from itertools import chain, groupby
 
-from sql import Literal, Null
+from sql import Null
 from sql.aggregate import Count
 from sql.functions import CharLength
 
@@ -458,7 +458,7 @@
                             subquery.payment_term,
                             subquery.invoice_method,
                             ],
-                        order_by=Count(Literal(1)).desc))
+                        order_by=Count().desc))
                 row = cursor.fetchone()
                 if row:
                     self.currency, self.payment_term, self.invoice_method = row
diff -r bb52a833e823 -r ce972acc1cf2 modules/purchase/pyproject.toml
--- a/modules/purchase/pyproject.toml   Tue Nov 25 13:27:24 2025 +0100
+++ b/modules/purchase/pyproject.toml   Thu Dec 25 09:47:23 2025 +0100
@@ -51,7 +51,7 @@
 "" = "trytond/modules/purchase"
 
 [tool.hatch.metadata.hooks.tryton]
-dependencies = ['python-sql >= 0.4']
+dependencies = ['python-sql >= 1.4']
 copyright = 'COPYRIGHT'
 readme = 'README.rst'
 
diff -r bb52a833e823 -r ce972acc1cf2 
modules/sale_opportunity/opportunity_reporting.py
--- a/modules/sale_opportunity/opportunity_reporting.py Tue Nov 25 13:27:24 
2025 +0100
+++ b/modules/sale_opportunity/opportunity_reporting.py Thu Dec 25 09:47:23 
2025 +0100
@@ -120,7 +120,7 @@
         return [
             cls._column_id(tables, withs).as_('id'),
             opportunity.company.as_('company'),
-            Count(Literal(1)).as_('number'),
+            Count().as_('number'),
             Sum(opportunity.amount).as_('amount'),
             Sum(Case(
                     (opportunity.state.in_(cls._converted_states()),
diff -r bb52a833e823 -r ce972acc1cf2 modules/sale_opportunity/pyproject.toml
--- a/modules/sale_opportunity/pyproject.toml   Tue Nov 25 13:27:24 2025 +0100
+++ b/modules/sale_opportunity/pyproject.toml   Thu Dec 25 09:47:23 2025 +0100
@@ -54,7 +54,7 @@
 [tool.hatch.metadata.hooks.tryton]
 dependencies = [
     'python-dateutil',
-    'python-sql >= 0.4',
+    'python-sql >= 1.4',
     ]
 copyright = 'COPYRIGHT'
 readme = 'README.rst'
diff -r bb52a833e823 -r ce972acc1cf2 
trytond/trytond/backend/postgresql/database.py
--- a/trytond/trytond/backend/postgresql/database.py    Tue Nov 25 13:27:24 
2025 +0100
+++ b/trytond/trytond/backend/postgresql/database.py    Thu Dec 25 09:47:23 
2025 +0100
@@ -489,7 +489,7 @@
                 'WHERE relname = %s',
                 (from_item._name,))
         else:
-            cursor.execute(*from_item.select(Count(Literal('*'))))
+            cursor.execute(*from_item.select(Count()))
         return cursor.fetchone()[0]
 
     def notify(self, connection, channel, payload):
diff -r bb52a833e823 -r ce972acc1cf2 trytond/trytond/backend/sqlite/database.py
--- a/trytond/trytond/backend/sqlite/database.py        Tue Nov 25 13:27:24 
2025 +0100
+++ b/trytond/trytond/backend/sqlite/database.py        Thu Dec 25 09:47:23 
2025 +0100
@@ -742,7 +742,7 @@
 
     def estimated_count(self, connection, table):
         cursor = connection.cursor()
-        cursor.execute(*table.select(Count(Literal('*'))))
+        cursor.execute(*table.select(Count()))
         return cursor.fetchone()[0]
 
     @classmethod
diff -r bb52a833e823 -r ce972acc1cf2 trytond/trytond/ir/trigger.py
--- a/trytond/trytond/ir/trigger.py     Tue Nov 25 13:27:24 2025 +0100
+++ b/trytond/trytond/ir/trigger.py     Thu Dec 25 09:47:23 2025 +0100
@@ -208,7 +208,7 @@
                 sub_ids = list(sub_ids)
                 red_sql = reduce_ids(trigger_log.record_id, sub_ids)
                 cursor.execute(*trigger_log.select(
-                        trigger_log.record_id, Count(Literal(1)),
+                        trigger_log.record_id, Count(),
                         where=red_sql & (trigger_log.trigger == self.id),
                         group_by=trigger_log.record_id))
                 number = dict(cursor)
diff -r bb52a833e823 -r ce972acc1cf2 trytond/trytond/model/modelsql.py
--- a/trytond/trytond/model/modelsql.py Tue Nov 25 13:27:24 2025 +0100
+++ b/trytond/trytond/model/modelsql.py Thu Dec 25 09:47:23 2025 +0100
@@ -1941,9 +1941,9 @@
             if (limit is not None and limit < cls.estimated_count()) or offset:
                 select = table.select(
                     Literal(1), where=expression, limit=limit, offset=offset
-                    ).select(Count(Literal('*')))
+                    ).select(Count())
             else:
-                select = table.select(Count(Literal('*')), where=expression)
+                select = table.select(Count(), where=expression)
             if query:
                 return select
             else:
diff -r bb52a833e823 -r ce972acc1cf2 trytond/trytond/res/notification.py
--- a/trytond/trytond/res/notification.py       Tue Nov 25 13:27:24 2025 +0100
+++ b/trytond/trytond/res/notification.py       Thu Dec 25 09:47:23 2025 +0100
@@ -91,7 +91,7 @@
         notification = cls.__table__()
         cursor = Transaction().connection.cursor()
         cursor.execute(*notification.select(
-                notification.user, Count(Literal('*')),
+                notification.user, Count(),
                 where=((notification.user.in_(list(notifications_by_user)))
                     & notification.unread),
                 group_by=[notification.user]))
diff -r bb52a833e823 -r ce972acc1cf2 trytond/trytond/res/user.py
--- a/trytond/trytond/res/user.py       Tue Nov 25 13:27:24 2025 +0100
+++ b/trytond/trytond/res/user.py       Thu Dec 25 09:47:23 2025 +0100
@@ -812,7 +812,7 @@
     def count(cls, login, device_cookie=None):
         cursor = Transaction().connection.cursor()
         table = cls.__table__()
-        cursor.execute(*table.select(Count(Literal('*')),
+        cursor.execute(*table.select(Count(),
                 where=(table.login == login)
                 & (table.device_cookie == device_cookie)
                 & (table.create_date >= cls.delay())))
@@ -825,7 +825,7 @@
         table = cls.__table__()
         _, ip_network = transaction.remote_address()
         ip_network = str(ip_network) if ip_network else None
-        cursor.execute(*table.select(Count(Literal('*')),
+        cursor.execute(*table.select(Count(),
                 where=(table.ip_network == ip_network)
                 & (table.create_date >= cls.delay())))
         return cursor.fetchone()[0]

Reply via email to